├── Chapter10 ├── 01_replicationcontroller-example │ └── nginx-replicationcontroller.yaml └── 02_replicaset-example │ ├── nginx-pod-bare.yaml │ ├── nginx-replicaset-expressions.yaml │ ├── nginx-replicaset-livenessprobe.yaml │ └── nginx-replicaset.yaml ├── Chapter11 └── 01_deployment-example │ ├── nginx-deployment-readinessprobe.yaml │ ├── nginx-deployment-rollingupdate.yaml │ ├── nginx-deployment.yaml │ └── nginx-service.yaml ├── Chapter12 └── 01_statefulset-example │ ├── nginx-client-service.yaml │ ├── nginx-headless-service.yaml │ ├── nginx-statefulset-rollingupdate.yaml │ └── nginx-statefulset.yaml ├── Chapter13 ├── 01_daemonset-example │ ├── nginx-daemon-headless-service.yaml │ └── nginx-daemonset.yaml └── 02_daemonset-prometheus-nodeexporter │ └── node-exporter.yaml ├── Chapter17 └── 01_helm │ └── bitnami │ └── wordpress │ ├── .helmignore │ ├── Chart.lock │ ├── Chart.yaml │ ├── README.md │ ├── ci │ ├── ct-values.yaml │ ├── ingress-wildcard-values.yaml │ ├── values-hpa-pdb.yaml │ ├── values-memcached.yaml │ └── values-metrics-and-ingress.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── externaldb-secrets.yaml │ ├── extra-list.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── metrics-svc.yaml │ ├── pdb.yaml │ ├── postinit-configmap.yaml │ ├── pvc.yaml │ ├── secrets.yaml │ ├── servicemonitor.yaml │ ├── svc.yaml │ ├── tests │ │ └── test-mariadb-connection.yaml │ └── tls-secrets.yaml │ ├── values.schema.json │ └── values.yaml ├── Chapter18 ├── 01_serviceaccount │ ├── example-account-serviceaccount.yaml │ ├── pod-reader-role.yaml │ └── read-pods-rolebinding.yaml ├── 02_rbac │ ├── pod-logger-serviceaccount.yaml │ ├── pod-logger-static-pod.yaml │ ├── pod-reader-role.yaml │ └── read-pods-rolebinding.yaml └── 03_aks-aad-rbac │ └── aks-pod-writer.json ├── Chapter19 ├── 01_nodename │ └── nginx-deployment.yaml ├── 02_nodeselector │ └── nginx-deployment.yaml ├── 03_affinity │ └── nginx-deployment.yaml └── 04_taints │ └── nginx-deployment.yaml ├── Chapter20 ├── 01_resource-requests-and-limits │ └── nginx-deployment.yaml ├── 02_vpa │ ├── hamster-deployment.yaml │ └── hamster-vpa.yaml ├── 03_hpa │ ├── deployment-reader-role.yaml │ ├── elastic-hamster-deployment.yaml │ ├── elastic-hamster-hpa.yaml │ ├── elastic-hamster-serviceaccount.yaml │ └── read-deployments-rolebinding.yaml └── 04_clusterautoscaler │ ├── deployment-reader-role.yaml │ ├── elastic-hamster-deployment.yaml │ ├── elastic-hamster-hpa.yaml │ ├── elastic-hamster-serviceaccount.yaml │ └── read-deployments-rolebinding.yaml ├── Chapter21 ├── 01_services-recap │ ├── nginx-deployment.yaml │ ├── nginx-service-clusterip.yaml │ └── nginx-service-nodeport.yaml ├── 02_ingress │ ├── example-ingress.yaml │ ├── example-services.yaml │ └── nginx-ingresscontroller-cloud.yaml └── 03_aks-agic │ ├── example-ingress.yaml │ └── example-services.yaml ├── LICENSE └── README.md /Chapter10/01_replicationcontroller-example/nginx-replicationcontroller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | name: nginx-replicationcontroller-example 5 | spec: 6 | replicas: 3 7 | selector: 8 | app: nginx 9 | environment: test 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx 14 | environment: test 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx:1.17 19 | ports: 20 | - containerPort: 80 21 | -------------------------------------------------------------------------------- /Chapter10/02_replicaset-example/nginx-pod-bare.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-bare-example 5 | labels: 6 | app: nginx 7 | environment: test 8 | spec: 9 | containers: 10 | - name: nginx 11 | image: nginx:1.17 12 | ports: 13 | - containerPort: 80 14 | -------------------------------------------------------------------------------- /Chapter10/02_replicaset-example/nginx-replicaset-expressions.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: ReplicaSet 3 | metadata: 4 | name: nginx-replicaset-example 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | matchExpressions: 11 | - key: environment 12 | operator: In 13 | values: 14 | - test 15 | - dev 16 | template: 17 | metadata: 18 | labels: 19 | app: nginx 20 | environment: test 21 | spec: 22 | containers: 23 | - name: nginx 24 | image: nginx:1.17 25 | ports: 26 | - containerPort: 80 27 | -------------------------------------------------------------------------------- /Chapter10/02_replicaset-example/nginx-replicaset-livenessprobe.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: ReplicaSet 3 | metadata: 4 | name: nginx-replicaset-livenessprobe-example 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | environment: test 16 | spec: 17 | containers: 18 | - name: nginx 19 | image: nginx:1.17 20 | ports: 21 | - containerPort: 80 22 | livenessProbe: 23 | httpGet: 24 | path: / 25 | port: 80 26 | initialDelaySeconds: 2 27 | periodSeconds: 2 28 | -------------------------------------------------------------------------------- /Chapter10/02_replicaset-example/nginx-replicaset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: ReplicaSet 3 | metadata: 4 | name: nginx-replicaset-example 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | environment: test 16 | spec: 17 | containers: 18 | - name: nginx 19 | image: nginx:1.17 20 | ports: 21 | - containerPort: 80 22 | -------------------------------------------------------------------------------- /Chapter11/01_deployment-example/nginx-deployment-readinessprobe.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | minReadySeconds: 10 12 | strategy: 13 | type: RollingUpdate 14 | rollingUpdate: 15 | maxUnavailable: 1 16 | maxSurge: 1 17 | template: 18 | metadata: 19 | labels: 20 | app: nginx 21 | environment: test 22 | spec: 23 | containers: 24 | - name: nginx 25 | image: nginx:1.17 26 | ports: 27 | - containerPort: 80 28 | command: 29 | - /bin/sh 30 | - -c 31 | - | 32 | touch /usr/share/nginx/html/ready 33 | echo "You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html 34 | nginx -g "daemon off;" 35 | readinessProbe: 36 | httpGet: 37 | path: /ready 38 | port: 80 39 | initialDelaySeconds: 5 40 | periodSeconds: 2 41 | timeoutSeconds: 10 42 | successThreshold: 1 43 | failureThreshold: 2 44 | -------------------------------------------------------------------------------- /Chapter11/01_deployment-example/nginx-deployment-rollingupdate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | minReadySeconds: 10 12 | strategy: 13 | type: RollingUpdate 14 | rollingUpdate: 15 | maxUnavailable: 1 16 | maxSurge: 1 17 | template: 18 | metadata: 19 | labels: 20 | app: nginx 21 | environment: test 22 | spec: 23 | containers: 24 | - name: nginx 25 | image: nginx:1.17 26 | ports: 27 | - containerPort: 80 28 | command: 29 | - /bin/sh 30 | - -c 31 | - | 32 | touch /usr/share/nginx/html/ready 33 | echo "You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html 34 | nginx -g "daemon off;" 35 | readinessProbe: 36 | httpGet: 37 | path: /ready 38 | port: 80 39 | initialDelaySeconds: 5 40 | periodSeconds: 2 41 | timeoutSeconds: 10 42 | successThreshold: 1 43 | failureThreshold: 2 44 | -------------------------------------------------------------------------------- /Chapter11/01_deployment-example/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | minReadySeconds: 10 12 | strategy: 13 | type: RollingUpdate 14 | rollingUpdate: 15 | maxUnavailable: 1 16 | maxSurge: 1 17 | template: 18 | metadata: 19 | labels: 20 | app: nginx 21 | environment: test 22 | spec: 23 | containers: 24 | - name: nginx 25 | image: nginx:1.17 26 | ports: 27 | - containerPort: 80 28 | -------------------------------------------------------------------------------- /Chapter11/01_deployment-example/nginx-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-service-example 5 | spec: 6 | selector: 7 | app: nginx 8 | environment: test 9 | type: LoadBalancer 10 | ports: 11 | - port: 80 12 | protocol: TCP 13 | targetPort: 80 14 | -------------------------------------------------------------------------------- /Chapter12/01_statefulset-example/nginx-client-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-client 5 | spec: 6 | selector: 7 | app: nginx-stateful 8 | environment: test 9 | type: LoadBalancer 10 | ports: 11 | - port: 80 12 | protocol: TCP 13 | targetPort: 80 14 | -------------------------------------------------------------------------------- /Chapter12/01_statefulset-example/nginx-headless-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-headless 5 | spec: 6 | selector: 7 | app: nginx-stateful 8 | environment: test 9 | clusterIP: None 10 | ports: 11 | - port: 80 12 | protocol: TCP 13 | targetPort: 80 14 | -------------------------------------------------------------------------------- /Chapter12/01_statefulset-example/nginx-statefulset-rollingupdate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: nginx-statefulset-example 5 | spec: 6 | replicas: 3 7 | serviceName: nginx-headless 8 | podManagementPolicy: OrderedReady 9 | updateStrategy: 10 | type: RollingUpdate 11 | rollingUpdate: 12 | partition: 0 13 | selector: 14 | matchLabels: 15 | app: nginx-stateful 16 | environment: test 17 | template: 18 | metadata: 19 | labels: 20 | app: nginx-stateful 21 | environment: test 22 | spec: 23 | containers: 24 | - name: nginx 25 | image: nginx:1.17 26 | ports: 27 | - containerPort: 80 28 | volumeMounts: 29 | - name: nginx-data 30 | mountPath: /usr/share/nginx/html 31 | command: 32 | - /bin/sh 33 | - -c 34 | - | 35 | echo "You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html 36 | nginx -g "daemon off;" 37 | volumeClaimTemplates: 38 | - metadata: 39 | name: nginx-data 40 | spec: 41 | accessModes: [ "ReadWriteOnce" ] 42 | resources: 43 | requests: 44 | storage: 1Gi 45 | -------------------------------------------------------------------------------- /Chapter12/01_statefulset-example/nginx-statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: nginx-statefulset-example 5 | spec: 6 | replicas: 3 7 | serviceName: nginx-headless 8 | selector: 9 | matchLabels: 10 | app: nginx-stateful 11 | environment: test 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx-stateful 16 | environment: test 17 | spec: 18 | containers: 19 | - name: nginx 20 | image: nginx:1.17 21 | ports: 22 | - containerPort: 80 23 | volumeMounts: 24 | - name: nginx-data 25 | mountPath: /usr/share/nginx/html 26 | command: 27 | - /bin/sh 28 | - -c 29 | - | 30 | echo "You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html 31 | nginx -g "daemon off;" 32 | volumeClaimTemplates: 33 | - metadata: 34 | name: nginx-data 35 | spec: 36 | accessModes: [ "ReadWriteOnce" ] 37 | resources: 38 | requests: 39 | storage: 1Gi 40 | -------------------------------------------------------------------------------- /Chapter13/01_daemonset-example/nginx-daemon-headless-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-daemon-headless 5 | spec: 6 | selector: 7 | app: nginx-daemon 8 | environment: test 9 | clusterIP: None 10 | ports: 11 | - port: 80 12 | protocol: TCP 13 | targetPort: 80 14 | -------------------------------------------------------------------------------- /Chapter13/01_daemonset-example/nginx-daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: nginx-daemonset-example 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: nginx-daemon 9 | environment: test 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx-daemon 14 | environment: test 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx:1.17 19 | ports: 20 | - containerPort: 80 21 | env: 22 | - name: NODE_IP 23 | valueFrom: 24 | fieldRef: 25 | fieldPath: status.hostIP 26 | command: 27 | - /bin/sh 28 | - -c 29 | - | 30 | echo "You have been served by Pod running on Node with IP address: $(NODE_IP)" > /usr/share/nginx/html/index.html 31 | nginx -g "daemon off;" 32 | -------------------------------------------------------------------------------- /Chapter13/02_daemonset-prometheus-nodeexporter/node-exporter.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Service 3 | apiVersion: v1 4 | metadata: 5 | name: node-exporter 6 | spec: 7 | selector: 8 | app: node-exporter 9 | environment: test 10 | clusterIP: None 11 | ports: 12 | - name: node-exporter 13 | protocol: TCP 14 | port: 9100 15 | targetPort: 9100 16 | --- 17 | apiVersion: apps/v1 18 | kind: DaemonSet 19 | metadata: 20 | name: node-exporter 21 | spec: 22 | selector: 23 | matchLabels: 24 | app: node-exporter 25 | environment: test 26 | template: 27 | metadata: 28 | labels: 29 | app: node-exporter 30 | environment: test 31 | spec: 32 | hostPID: true 33 | hostIPC: true 34 | hostNetwork: true 35 | containers: 36 | - ports: 37 | - containerPort: 9100 38 | protocol: TCP 39 | securityContext: 40 | privileged: true 41 | image: prom/node-exporter 42 | args: 43 | - --path.procfs 44 | - /host/proc 45 | - --path.sysfs 46 | - /host/sys 47 | - --collector.filesystem.ignored-mount-points 48 | - '"^/(sys|proc|dev|host|etc)($|/)"' 49 | name: node-exporter 50 | volumeMounts: 51 | - name: dev 52 | mountPath: /host/dev 53 | - name: proc 54 | mountPath: /host/proc 55 | - name: sys 56 | mountPath: /host/sys 57 | - name: rootfs 58 | mountPath: /rootfs 59 | volumes: 60 | - name: proc 61 | hostPath: 62 | path: /proc 63 | - name: dev 64 | hostPath: 65 | path: /dev 66 | - name: sys 67 | hostPath: 68 | path: /sys 69 | - name: rootfs 70 | hostPath: 71 | path: / 72 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: mariadb 3 | repository: https://charts.bitnami.com/bitnami 4 | version: 9.3.5 5 | - name: memcached 6 | repository: https://charts.bitnami.com/bitnami 7 | version: 5.8.0 8 | - name: common 9 | repository: https://charts.bitnami.com/bitnami 10 | version: 1.4.1 11 | digest: sha256:3d4aa1a5f506edde9b515c7831b9cdd86ca45f880f2ac500720a649518c05072 12 | generated: "2021-03-23T09:42:20.224652317Z" 13 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/Chart.yaml: -------------------------------------------------------------------------------- 1 | annotations: 2 | category: CMS 3 | apiVersion: v2 4 | appVersion: 5.7.0 5 | dependencies: 6 | - condition: mariadb.enabled 7 | name: mariadb 8 | repository: https://charts.bitnami.com/bitnami 9 | version: 9.x.x 10 | - condition: memcached.enabled 11 | name: memcached 12 | repository: https://charts.bitnami.com/bitnami 13 | version: 5.x.x 14 | - name: common 15 | repository: https://charts.bitnami.com/bitnami 16 | tags: 17 | - bitnami-common 18 | version: 1.x.x 19 | description: Web publishing platform for building blogs and websites. 20 | engine: gotpl 21 | home: https://github.com/bitnami/charts/tree/master/bitnami/wordpress 22 | icon: https://bitnami.com/assets/stacks/wordpress/img/wordpress-stack-220x234.png 23 | keywords: 24 | - application 25 | - blog 26 | - cms 27 | - http 28 | - php 29 | - web 30 | - wordpress 31 | maintainers: 32 | - email: containers@bitnami.com 33 | name: Bitnami 34 | name: wordpress 35 | sources: 36 | - https://github.com/bitnami/bitnami-docker-wordpress 37 | - http://www.wordpress.com/ 38 | version: 10.7.2 39 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/README.md: -------------------------------------------------------------------------------- 1 | **NOTE:** Copy of Helm Chart from https://github.com/bitnami/charts to ensure availability even if the Chart is moved. 2 | 3 | # WordPress 4 | 5 | [WordPress](https://wordpress.org/) is one of the most versatile open source content management systems on the market. A publishing platform for building blogs and websites. 6 | 7 | ## TL;DR 8 | 9 | ```console 10 | $ helm repo add bitnami https://charts.bitnami.com/bitnami 11 | $ helm install my-release bitnami/wordpress 12 | ``` 13 | 14 | ## Introduction 15 | 16 | This chart bootstraps a [WordPress](https://github.com/bitnami/bitnami-docker-wordpress) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. 17 | 18 | It also packages the [Bitnami MariaDB chart](https://github.com/bitnami/charts/tree/master/bitnami/mariadb) which is required for bootstrapping a MariaDB deployment for the database requirements of the WordPress application, and the [Bitnami Memcached chart](https://github.com/bitnami/charts/tree/master/bitnami/memcached) that can be used to cache database queries. 19 | 20 | Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This chart has been tested to work with NGINX Ingress, cert-manager, fluentd and Prometheus on top of the [BKPR](https://kubeprod.io/). 21 | 22 | ## Prerequisites 23 | 24 | - Kubernetes 1.12+ 25 | - Helm 3.1.0 26 | - PV provisioner support in the underlying infrastructure 27 | - ReadWriteMany volumes for deployment scaling 28 | 29 | ## Installing the Chart 30 | 31 | To install the chart with the release name `my-release`: 32 | 33 | ```console 34 | helm install my-release bitnami/wordpress 35 | ``` 36 | 37 | The command deploys WordPress on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. 38 | 39 | > **Tip**: List all releases using `helm list` 40 | 41 | ## Uninstalling the Chart 42 | 43 | To uninstall/delete the `my-release` deployment: 44 | 45 | ```console 46 | helm delete my-release 47 | ``` 48 | 49 | The command removes all the Kubernetes components associated with the chart and deletes the release. 50 | 51 | ## Parameters 52 | 53 | The following table lists the configurable parameters of the WordPress chart and their default values per section/component: 54 | 55 | ### Global parameters 56 | 57 | | Parameter | Description | Default | 58 | |---------------------------|-------------------------------------------------|---------------------------------------------------------| 59 | | `global.imageRegistry` | Global Docker image registry | `nil` | 60 | | `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | 61 | | `global.storageClass` | Global storage class for dynamic provisioning | `nil` | 62 | 63 | ### Common parameters 64 | 65 | | Parameter | Description | Default | 66 | |---------------------|----------------------------------------------------------------------|--------------------------------| 67 | | `nameOverride` | String to partially override common.names.fullname | `nil` | 68 | | `fullnameOverride` | String to fully override common.names.fullname | `nil` | 69 | | `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | 70 | | `commonLabels` | Labels to add to all deployed objects | `{}` | 71 | | `commonAnnotations` | Annotations to add to all deployed objects | `{}` | 72 | | `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `nil` | 73 | | `extraDeploy` | Array of extra objects to deploy with the release | `[]` (evaluated as a template) | 74 | 75 | ### WordPress parameters 76 | 77 | | Parameter | Description | Default | 78 | |-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| 79 | | `image.registry` | WordPress image registry | `docker.io` | 80 | | `image.repository` | WordPress image name | `bitnami/wordpress` | 81 | | `image.tag` | WordPress image tag | `{TAG_NAME}` | 82 | | `image.pullPolicy` | WordPress image pull policy | `IfNotPresent` | 83 | | `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | 84 | | `image.debug` | Specify if debug logs should be enabled | `false` | 85 | | `hostAliases` | Add deployment host aliases | `Check values.yaml` | 86 | | `wordpressSkipInstall` | Skip wizard installation when the external db already contains data from a previous WordPress installation [see](https://github.com/bitnami/bitnami-docker-wordpress#connect-wordpress-docker-container-to-an-existing-database) | `false` | 87 | | `wordpressUsername` | User of the application | `user` | 88 | | `existingSecret` | Name of the existing Wordpress Secret (it must contain a key named `wordpress-password`). When it's set, `wordpressPassword` is ignored | `nil` | 89 | | `serviceAccountName` | Name of a service account for the WordPress pods | `default` | 90 | | `wordpressPassword` | Application password | _random 10 character long alphanumeric string_ | 91 | | `wordpressEmail` | Admin email | `user@example.com` | 92 | | `wordpressFirstName` | First name | `FirstName` | 93 | | `wordpressLastName` | Last name | `LastName` | 94 | | `wordpressBlogName` | Blog name | `User's Blog!` | 95 | | `wordpressTablePrefix` | Table prefix | `wp_` | 96 | | `wordpressScheme` | Scheme to generate application URLs [`http`, `https`] | `http` | 97 | | `wordpressExtraConfigContent` | Add extra content to the configuration file | `""` | 98 | | `allowEmptyPassword` | Allow DB blank passwords | `true` | 99 | | `allowOverrideNone` | Set Apache AllowOverride directive to None | `false` | 100 | | `htaccessPersistenceEnabled` | Make `.htaccess` persistence so that it can be customized. [See](#disabling-htaccess) | `false` | 101 | | `customHTAccessCM` | Configmap with custom wordpress-htaccess.conf directives | `nil` | 102 | | `customPostInitScripts` | Custom post-init.d user scripts | `nil` | 103 | | `smtpHost` | SMTP host | `nil` | 104 | | `smtpPort` | SMTP port | `nil` | 105 | | `smtpUser` | SMTP user | `nil` | 106 | | `smtpPassword` | SMTP password | `nil` | 107 | | `smtpUsername` | User name for SMTP emails | `nil` | 108 | | `smtpProtocol` | SMTP protocol [`tls`, `ssl`, `none`] | `nil` | 109 | | `smtpExistingPassword` | Existing secret containing SMTP password in key `smtp-password` | `nil` | 110 | | `command` | Override default container command (useful when using custom images) | `nil` | 111 | | `args` | Override default container args (useful when using custom images) | `nil` | 112 | | `extraEnvVars` | Extra environment variables to be set on WordPress container | `{}` | 113 | | `extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `nil` | 114 | | `extraEnvVarsSecret` | Name of existing Secret containing extra env vars | `nil` | 115 | 116 | ### WordPress deployment parameters 117 | 118 | | Parameter | Description | Default | 119 | |-----------------------------|-------------------------------------------------------------------------------------------|--------------------------------------| 120 | | `replicaCount` | Number of WordPress Pods to run | `1` | 121 | | `containerPorts.http` | HTTP port to expose at container level | `8080` | 122 | | `containerPorts.https` | HTTPS port to expose at container level | `8443` | 123 | | `podSecurityContext` | WordPress pods' Security Context | Check `values.yaml` file | 124 | | `containerSecurityContext` | WordPress containers' Security Context | Check `values.yaml` file | 125 | | `resources.limits` | The resources limits for the WordPress container | `{}` | 126 | | `resources.requests` | The requested resources for the WordPress container | `{"memory": "512Mi", "cpu": "300m"}` | 127 | | `livenessProbe` | Liveness probe configuration for WordPress | Check `values.yaml` file | 128 | | `readinessProbe` | Readiness probe configuration for WordPress | Check `values.yaml` file | 129 | | `customLivenessProbe` | Override default liveness probe | `nil` | 130 | | `customReadinessProbe` | Override default readiness probe | `nil` | 131 | | `updateStrategy` | Set up update strategy | `RollingUpdate` | 132 | | `schedulerName` | Name of the alternate scheduler | `nil` | 133 | | `podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | 134 | | `nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | 135 | | `nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set. | `""` | 136 | | `nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set. | `[]` | 137 | | `affinity` | Affinity for pod assignment | `{}` (evaluated as a template) | 138 | | `nodeSelector` | Node labels for pod assignment | `{}` (evaluated as a template) | 139 | | `tolerations` | Tolerations for pod assignment | `[]` (evaluated as a template) | 140 | | `podLabels` | Extra labels for WordPress pods | `{}` | 141 | | `podAnnotations` | Annotations for WordPress pods | `{}` | 142 | | `extraVolumeMounts` | Additional volume mounts | `[]` | 143 | | `extraVolumes` | Additional volumes | `[]` | 144 | | `initContainers` | Add additional init containers to the WordPress pods | `{}` (evaluated as a template) | 145 | | `sidecars` | Attach additional sidecar containers to the pod | `{}` (evaluated as a template) | 146 | 147 | ### Exposure parameters 148 | 149 | | Parameter | Description | Default | 150 | |------------------------------------|-------------------------------------------------------------------------------|--------------------------------| 151 | | `service.type` | Kubernetes Service type | `LoadBalancer` | 152 | | `service.port` | Service HTTP port | `80` | 153 | | `service.httpsPort` | Service HTTPS port | `443` | 154 | | `service.httpsTargetPort` | Service Target HTTPS port | `https` | 155 | | `service.nodePorts.http` | Kubernetes http node port | `""` | 156 | | `service.nodePorts.https` | Kubernetes https node port | `""` | 157 | | `service.extraPorts` | Extra ports to expose in the service (normally used with the `sidecar` value) | `nil` | 158 | | `service.clusterIP` | WordPress service clusterIP IP | `None` | 159 | | `service.loadBalancerSourceRanges` | Restricts access for LoadBalancer (only with `service.type: LoadBalancer`) | `[]` | 160 | | `service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` | 161 | | `service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | 162 | | `service.annotations` | Service annotations | `{}` (evaluated as a template) | 163 | | `ingress.enabled` | Enable ingress controller resource | `false` | 164 | | `ingress.certManager` | Add annotations for cert-manager | `false` | 165 | | `ingress.hostname` | Default host for the ingress resource | `wordpress.local` | 166 | | `ingress.path` | Default path for the ingress resource | `/` | 167 | | `ingress.tls` | Create TLS Secret | `false` | 168 | | `ingress.annotations` | Ingress annotations | `[]` (evaluated as a template) | 169 | | `ingress.extraHosts[0].name` | Additional hostnames to be covered | `nil` | 170 | | `ingress.extraHosts[0].path` | Additional hostnames to be covered | `nil` | 171 | | `ingress.extraPaths` | Additional arbitrary path/backend objects | `nil` | 172 | | `ingress.extraTls[0].hosts[0]` | TLS configuration for additional hostnames to be covered | `nil` | 173 | | `ingress.extraTls[0].secretName` | TLS configuration for additional hostnames to be covered | `nil` | 174 | | `ingress.secrets[0].name` | TLS Secret Name | `nil` | 175 | | `ingress.secrets[0].certificate` | TLS Secret Certificate | `nil` | 176 | | `ingress.secrets[0].key` | TLS Secret Key | `nil` | 177 | 178 | ### Persistence parameters 179 | 180 | | Parameter | Description | Default | 181 | |-----------------------------|------------------------------------------|---------------------------------------------| 182 | | `persistence.enabled` | Enable persistence using PVC | `true` | 183 | | `persistence.existingClaim` | Enable persistence using an existing PVC | `nil` | 184 | | `persistence.storageClass` | PVC Storage Class | `nil` (uses alpha storage class annotation) | 185 | | `persistence.accessModes` | PVC Access Modes | `[ReadWriteOnce]` | 186 | | `persistence.size` | PVC Storage Request | `10Gi` | 187 | | `persistence.dataSource` | PVC data source | `{}` | 188 | 189 | ### Database parameters 190 | 191 | | Parameter | Description | Default | 192 | |-------------------------------------------|------------------------------------------------------|------------------------------------------------| 193 | | `mariadb.enabled` | Deploy MariaDB container(s) | `true` | 194 | | `mariadb.architecture` | MariaDB architecture (`standalone` or `replication`) | `standalone` | 195 | | `mariadb.auth.rootPassword` | Password for the MariaDB `root` user | _random 10 character alphanumeric string_ | 196 | | `mariadb.auth.database` | Database name to create | `bitnami_wordpress` | 197 | | `mariadb.auth.username` | Database user to create | `bn_wordpress` | 198 | | `mariadb.auth.password` | Password for the database | _random 10 character long alphanumeric string_ | 199 | | `mariadb.primary.persistence.enabled` | Enable database persistence using PVC | `true` | 200 | | `mariadb.primary.persistence.accessModes` | Database Persistent Volume Access Modes | `[ReadWriteOnce]` | 201 | | `mariadb.primary.persistence.size` | Database Persistent Volume Size | `8Gi` | 202 | | `externalDatabase.host` | Host of the external database | `localhost` | 203 | | `externalDatabase.user` | Existing username in the external db | `bn_wordpress` | 204 | | `externalDatabase.password` | Password for the above username | `nil` | 205 | | `externalDatabase.database` | Name of the existing database | `bitnami_wordpress` | 206 | | `externalDatabase.port` | Database port number | `3306` | 207 | | `externalDatabase.existingSecret` | Name of the database existing Secret Object | `nil` | 208 | | `memcached.enabled` | Deploy Memcached for caching database queries | `false` | 209 | 210 | ### Volume Permissions parameters 211 | 212 | | Parameter | Description | Default | 213 | |-----------------------------------------------|----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| 214 | | `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | 215 | | `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | 216 | | `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/bitnami-shell` | 217 | | `volumePermissions.image.tag` | Init container volume-permissions image tag | `"10"` | 218 | | `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | 219 | | `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | 220 | | `volumePermissions.resources.limits` | Init container volume-permissions resource limits | `{}` | 221 | | `volumePermissions.resources.requests` | Init container volume-permissions resource requests | `{}` | 222 | | `volumePermissions.securityContext.*` | Other container security context to be included as-is in the container spec | `{}` | 223 | | `volumePermissions.securityContext.runAsUser` | User ID for the init container (when facing issues in OpenShift or uid unknown, try value "auto") | `0` | 224 | 225 | ### Metrics parameters 226 | 227 | | Parameter | Description | Default | 228 | |-------------------------------------------|------------------------------------------------------------------------------|--------------------------------------------------------------| 229 | | `metrics.enabled` | Start a side-car prometheus exporter | `false` | 230 | | `metrics.image.registry` | Apache exporter image registry | `docker.io` | 231 | | `metrics.image.repository` | Apache exporter image name | `bitnami/apache-exporter` | 232 | | `metrics.image.tag` | Apache exporter image tag | `{TAG_NAME}` | 233 | | `metrics.image.pullPolicy` | Image pull policy | `IfNotPresent` | 234 | | `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | 235 | | `metrics.service.port` | Service Metrics port | `9117` | 236 | | `metrics.service.annotations` | Annotations for enabling prometheus to access the metrics endpoints | `{prometheus.io/scrape: "true", prometheus.io/port: "9117"}` | 237 | | `metrics.resources.limits` | The resources limits for the metrics exporter container | `{}` | 238 | | `metrics.resources.requests` | The requested resources for the metrics exporter container | `{}` | 239 | | `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using PrometheusOperator | `false` | 240 | | `metrics.serviceMonitor.namespace` | Namespace where servicemonitor resource should be created | `nil` | 241 | | `metrics.serviceMonitor.interval` | Specify the interval at which metrics should be scraped | `30s` | 242 | | `metrics.serviceMonitor.scrapeTimeout` | Specify the timeout after which the scrape is ended | `nil` | 243 | | `metrics.serviceMonitor.relabellings` | Specify Metric Relabellings to add to the scrape endpoint | `nil` | 244 | | `metrics.serviceMonitor.honorLabels` | honorLabels chooses the metric's labels on collisions with target labels. | `false` | 245 | | `metrics.serviceMonitor.additionalLabels` | Used to pass Labels that are required by the Installed Prometheus Operator | `{}` | 246 | 247 | ### Other parameters 248 | 249 | | Parameter | Description | Default | 250 | |----------------------------|----------------------------------------------------------------|---------| 251 | | `pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` | 252 | | `pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `1` | 253 | | `pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `nil` | 254 | | `autoscaling.enabled` | Enable autoscaling for WordPress | `false` | 255 | | `autoscaling.minReplicas` | Minimum number of WordPress replicas | `1` | 256 | | `autoscaling.maxReplicas` | Maximum number of WordPress replicas | `11` | 257 | | `autoscaling.targetCPU` | Target CPU utilization percentage | `nil` | 258 | | `autoscaling.targetMemory` | Target Memory utilization percentage | `nil` | 259 | 260 | The above parameters map to the env variables defined in [bitnami/wordpress](http://github.com/bitnami/bitnami-docker-wordpress). For more information please refer to the [bitnami/wordpress](http://github.com/bitnami/bitnami-docker-wordpress) image documentation. 261 | 262 | Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, 263 | 264 | ```console 265 | helm install my-release \ 266 | --set wordpressUsername=admin \ 267 | --set wordpressPassword=password \ 268 | --set mariadb.auth.rootPassword=secretpassword \ 269 | bitnami/wordpress 270 | ``` 271 | 272 | The above command sets the WordPress administrator account username and password to `admin` and `password` respectively. Additionally, it sets the MariaDB `root` user password to `secretpassword`. 273 | 274 | > NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. 275 | 276 | Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, 277 | 278 | ```console 279 | helm install my-release -f values.yaml bitnami/wordpress 280 | ``` 281 | 282 | > **Tip**: You can use the default [values.yaml](values.yaml) 283 | 284 | ## Configuration and installation details 285 | 286 | ### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) 287 | 288 | It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. 289 | 290 | Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. 291 | 292 | ### Known limitations 293 | 294 | When performing admin operations that require activating the maintenance mode (such as updating a plugin or theme), it's activated in only one replica (see: [bug report](https://core.trac.wordpress.org/ticket/50797)). This implies that WP could be attending requests on other replicas while performing admin operations, with unpredictable consequences. 295 | 296 | To avoid that, you can manually activate/deactivate the maintenance mode on every replica using the WP CLI. For instance, if you installed WP with three replicas, you can run the commands below to activate the maintenance mode in all of them (assuming that the release name is `wordpress`): 297 | 298 | ```console 299 | kubectl exec $(kubectl get pods -l app.kubernetes.io/name=wordpress -o jsonpath='{.items[0].metadata.name}') -c wordpress -- wp maintenance-mode activate 300 | kubectl exec $(kubectl get pods -l app.kubernetes.io/name=wordpress -o jsonpath='{.items[1].metadata.name}') -c wordpress -- wp maintenance-mode activate 301 | kubectl exec $(kubectl get pods -l app.kubernetes.io/name=wordpress -o jsonpath='{.items[2].metadata.name}') -c wordpress -- wp maintenance-mode activate 302 | ``` 303 | 304 | ### External database support 305 | 306 | You may want to have WordPress connect to an external database rather than installing one inside your cluster. Typical reasons for this are to use a managed database service, or to share a common database server for all your applications. To achieve this, the chart allows you to specify credentials for an external database with the [`externalDatabase` parameter](#parameters). You should also disable the MariaDB installation with the `mariadb.enabled` option. Here is an example: 307 | 308 | ```console 309 | mariadb.enabled=false 310 | externalDatabase.host=myexternalhost 311 | externalDatabase.user=myuser 312 | externalDatabase.password=mypassword 313 | externalDatabase.database=mydatabase 314 | externalDatabase.port=3306 315 | ``` 316 | 317 | Refer to the [documentation on using an external database with WordPress](https://docs.bitnami.com/kubernetes/apps/wordpress/configuration/use-external-database/) and the [tutorial on integrating WordPress with a managed cloud database](https://docs.bitnami.com/tutorials/secure-wordpress-kubernetes-managed-database-ssl-upgrades/) for more information. 318 | 319 | ### Memcached 320 | 321 | This chart provides support for using Memcached to cache database queries improving the website performance. To enable this feature, set `memcached.enabled` to `true`. 322 | 323 | When this features is enabled, a Memcached server will be deployed in your K8s cluster using the Bitnami Memcached chart and the [W3 Total Cache](https://wordpress.org/plugins/w3-total-cache/) plugin will be activated and configured to use the Memcached server for database caching. 324 | 325 | ### Ingress 326 | 327 | This chart provides support for Ingress resources. If an Ingress controller, such as [nginx-ingress](https://kubeapps.com/charts/stable/nginx-ingress) or [traefik](https://kubeapps.com/charts/stable/traefik), that Ingress controller can be used to serve WordPress. 328 | 329 | To enable Ingress integration, set `ingress.enabled` to `true`. The `ingress.hostname` property can be used to set the host name. The `ingress.tls` parameter can be used to add the TLS configuration for this host. It is also possible to have more than one host, with a separate TLS configuration for each host. [Learn more about configuring and using Ingress](https://docs.bitnami.com/kubernetes/apps/wordpress/configuration/configure-use-ingress/). 330 | 331 | ### TLS secrets 332 | 333 | The chart also facilitates the creation of TLS secrets for use with the Ingress controller, with different options for certificate management. [Learn more about TLS secrets](https://docs.bitnami.com/kubernetes/apps/wordpress/administration/enable-tls/). 334 | 335 | ### `.htaccess` files 336 | 337 | For performance and security reasons, it is a good practice to configure Apache with the `AllowOverride None` directive. Instead of using `.htaccess` files, Apache will load the same directives at boot time. These directives are located in `/opt/bitnami/wordpress/wordpress-htaccess.conf`. 338 | 339 | By default, the container image includes all the default `.htaccess` files in WordPress (together with the default plugins). To enable this feature, install the chart with the value `allowOverrideNone=yes`. 340 | 341 | [Learn more about working with `.htaccess` files](https://docs.bitnami.com/kubernetes/apps/wordpress/configuration/understand-htaccess/). 342 | 343 | ## Persistence 344 | 345 | The [Bitnami WordPress](https://github.com/bitnami/bitnami-docker-wordpress) image stores the WordPress data and configurations at the `/bitnami` path of the container. Persistent Volume Claims are used to keep the data across deployments. [Learn more about persistence in the chart documentation](https://docs.bitnami.com/kubernetes/apps/wordpress/configuration/chart-persistence/). 346 | 347 | ### Additional environment variables 348 | 349 | In case you want to add extra environment variables (useful for advanced operations like custom init scripts), you can use the `extraEnvVars` property. 350 | 351 | ```yaml 352 | wordpress: 353 | extraEnvVars: 354 | - name: LOG_LEVEL 355 | value: error 356 | ``` 357 | 358 | Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` values. 359 | 360 | ### Sidecars 361 | 362 | If additional containers are needed in the same pod as WordPress (such as additional metrics or logging exporters), they can be defined using the `sidecars` parameter. If these sidecars export extra ports, extra port definitions can be added using the `service.extraPorts` parameter. [Learn more about configuring and using sidecar containers](https://docs.bitnami.com/kubernetes/apps/wordpress/administration/configure-use-sidecars/). 363 | 364 | ### Pod affinity 365 | 366 | This chart allows you to set your custom affinity using the `affinity` parameter. Find more information about Pod affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). 367 | 368 | As an alternative, use one of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/master/bitnami/common#affinities) chart. To do so, set the `podAffinityPreset`, `podAntiAffinityPreset`, or `nodeAffinityPreset` parameters. 369 | 370 | ## Troubleshooting 371 | 372 | Find more information about how to deal with common errors related to Bitnami’s Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). 373 | 374 | ## Upgrading 375 | 376 | ### To 10.0.0 377 | 378 | [On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. 379 | 380 | [Learn more about this change and related upgrade considerations](https://docs.bitnami.com/kubernetes/apps/wordpress/administration/upgrade-helm3/). 381 | 382 | #### Additional upgrade notes 383 | 384 | - MariaDB dependency version was bumped to a new major version that introduces several incompatabilitees. Therefore, backwards compatibility is not guaranteed unless an external database is used. Check [MariaDB Upgrading Notes](https://github.com/bitnami/charts/tree/master/bitnami/mariadb#to-800) for more information. 385 | - If you want to upgrade to this version from a previous one installed with Helm v3, there are two alternatives: 386 | - Install a new WordPress chart, and migrate your WordPress site using backup/restore tools such as [VaultPress](https://vaultpress.com/) or [All-in-One WP Migration](https://wordpress.org/plugins/all-in-one-wp-migration/). 387 | - Reuse the PVC used to hold the MariaDB data on your previous release. To do so, follow the instructions below (the following example assumes that the release name is `wordpress`). 388 | 389 | > Warning: please create a backup of your database before running any of these actions. The steps below would be only valid if your application (e.g. any plugins or custom code) is compatible with MariaDB 10.5. 390 | 391 | Obtain the credentials and the name of the PVC used to hold the MariaDB data on your current release: 392 | 393 | ```console 394 | $ export WORDPRESS_PASSWORD=$(kubectl get secret --namespace default wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode) 395 | $ export MARIADB_ROOT_PASSWORD=$(kubectl get secret --namespace default wordpress-mariadb -o jsonpath="{.data.mariadb-root-password}" | base64 --decode) 396 | $ export MARIADB_PASSWORD=$(kubectl get secret --namespace default wordpress-mariadb -o jsonpath="{.data.mariadb-password}" | base64 --decode) 397 | $ export MARIADB_PVC=$(kubectl get pvc -l app.kubernetes.io/instance=wordpress,app.kubernetes.io/name=mariadb,app.kubernetes.io/component=primary -o jsonpath="{.items[0].metadata.name}") 398 | ``` 399 | 400 | Upgrade your release (maintaining the version) disabling MariaDB and scaling WordPress replicas to 0: 401 | 402 | ```console 403 | $ helm upgrade wordpress bitnami/wordpress --set wordpressPassword=$WORDPRESS_PASSWORD --set replicaCount=0 --set mariadb.enabled=false --version 9.6.4 404 | ``` 405 | 406 | Finally, upgrade you release to `10.0.0` reusing the existing PVC, and enabling back MariaDB: 407 | 408 | ```console 409 | $ helm upgrade wordpress bitnami/wordpress --set mariadb.primary.persistence.existingClaim=$MARIADB_PVC --set mariadb.auth.rootPassword=$MARIADB_ROOT_PASSWORD --set mariadb.auth.password=$MARIADB_PASSWORD --set wordpressPassword=$WORDPRESS_PASSWORD 410 | ``` 411 | 412 | You should see the lines below in MariaDB container logs: 413 | 414 | ```console 415 | $ kubectl logs $(kubectl get pods -l app.kubernetes.io/instance=wordpress,app.kubernetes.io/name=mariadb,app.kubernetes.io/component=primary -o jsonpath="{.items[0].metadata.name}") 416 | ... 417 | mariadb 12:13:24.98 INFO ==> Using persisted data 418 | mariadb 12:13:25.01 INFO ==> Running mysql_upgrade 419 | ... 420 | ``` 421 | 422 | ### To 9.0.0 423 | 424 | The [Bitnami WordPress](https://github.com/bitnami/bitnami-docker-wordpress) image was migrated to a "non-root" user approach. Previously the container ran as the `root` user and the Apache daemon was started as the `daemon` user. From now on, both the container and the Apache daemon run as user `1001`. You can revert this behavior by setting the parameters `securityContext.runAsUser`, and `securityContext.fsGroup` to `0`. 425 | Chart labels and Ingress configuration were also adapted to follow the Helm charts best practices. 426 | 427 | Consequences: 428 | 429 | - The HTTP/HTTPS ports exposed by the container are now `8080/8443` instead of `80/443`. 430 | - No writing permissions will be granted on `wp-config.php` by default. 431 | - Backwards compatibility is not guaranteed. 432 | 433 | To upgrade to `9.0.0`, it's recommended to install a new WordPress chart, and migrate your WordPress site using backup/restore tools such as [VaultPress](https://vaultpress.com/) or [All-in-One WP Migration](https://wordpress.org/plugins/all-in-one-wp-migration/). 434 | 435 | ### To 8.0.0 436 | 437 | Helm performs a lookup for the object based on its group (apps), version (v1), and kind (Deployment). Also known as its GroupVersionKind, or GVK. Changing the GVK is considered a compatibility breaker from Kubernetes' point of view, so you cannot "upgrade" those objects to the new GVK in-place. Earlier versions of Helm 3 did not perform the lookup correctly which has since been fixed to match the spec. 438 | 439 | In https://github.com/helm/charts/pulls/12642 the `apiVersion` of the deployment resources was updated to `apps/v1` in tune with the api's deprecated, resulting in compatibility breakage. 440 | 441 | This major version signifies this change. 442 | 443 | ### To 3.0.0 444 | 445 | Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. 446 | Use the workaround below to upgrade from versions previous to `3.0.0`. The following example assumes that the release name is `wordpress`: 447 | 448 | ```console 449 | kubectl patch deployment wordpress-wordpress --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' 450 | kubectl delete statefulset wordpress-mariadb --cascade=false 451 | ``` 452 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/ci/ct-values.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | type: ClusterIP 3 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/ci/ingress-wildcard-values.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | type: ClusterIP 3 | 4 | ingress: 5 | enabled: true 6 | tls: true 7 | extraHosts: 8 | - name: "*.domain.tld" 9 | path: / 10 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/ci/values-hpa-pdb.yaml: -------------------------------------------------------------------------------- 1 | autoscaling: 2 | enabled: true 3 | pdb: 4 | create: true 5 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/ci/values-memcached.yaml: -------------------------------------------------------------------------------- 1 | memcached: 2 | enabled: true 3 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/ci/values-metrics-and-ingress.yaml: -------------------------------------------------------------------------------- 1 | ingress: 2 | enabled: true 3 | tls: true 4 | 5 | service: 6 | type: ClusterIP 7 | 8 | metrics: 9 | enabled: true 10 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 2 | ** Please be patient while the chart is being deployed ** 3 | 4 | Your WordPress site can be accessed through the following DNS name from within your cluster: 5 | 6 | {{ include "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} (port {{ .Values.service.port }}) 7 | 8 | To access your WordPress site from outside the cluster follow the steps below: 9 | 10 | {{- if .Values.ingress.enabled }} 11 | 12 | 1. Get the WordPress URL and associate WordPress hostname to your cluster external IP: 13 | 14 | export CLUSTER_IP=$(minikube ip) # On Minikube. Use: `kubectl cluster-info` on others K8s clusters 15 | echo "WordPress URL: http{{ if .Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.hostname }}/" 16 | echo "$CLUSTER_IP {{ .Values.ingress.hostname }}" | sudo tee -a /etc/hosts 17 | 18 | {{- else }} 19 | {{- $port := .Values.service.port | toString }} 20 | 21 | 1. Get the WordPress URL by running these commands: 22 | 23 | {{- if contains "NodePort" .Values.service.type }} 24 | 25 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }}) 26 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 27 | echo "WordPress URL: http://$NODE_IP:$NODE_PORT/" 28 | echo "WordPress Admin URL: http://$NODE_IP:$NODE_PORT/admin" 29 | 30 | {{- else if contains "LoadBalancer" .Values.service.type }} 31 | 32 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 33 | Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}' 34 | 35 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 36 | echo "WordPress URL: http://$SERVICE_IP{{- if ne $port "80" }}:{{ .Values.service.port }}{{ end }}/" 37 | echo "WordPress Admin URL: http://$SERVICE_IP{{- if ne $port "80" }}:{{ .Values.service.port }}{{ end }}/admin" 38 | 39 | {{- else if contains "ClusterIP" .Values.service.type }} 40 | 41 | kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "common.names.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }} & 42 | echo "WordPress URL: http://127.0.0.1{{- if ne $port "80" }}:{{ .Values.service.port }}{{ end }}//" 43 | echo "WordPress Admin URL: http://127.0.0.1{{- if ne $port "80" }}:{{ .Values.service.port }}{{ end }}//admin" 44 | 45 | {{- end }} 46 | {{- end }} 47 | 48 | 2. Open a browser and access WordPress using the obtained URL. 49 | 50 | 3. Login with the following credentials below to see your blog: 51 | 52 | echo Username: {{ .Values.wordpressUsername }} 53 | echo Password: $(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} -o jsonpath="{.data.wordpress-password}" | base64 --decode) 54 | 55 | {{- if .Values.metrics.enabled }} 56 | 57 | You can access Apache Prometheus metrics following the steps below: 58 | 59 | 1. Get the Apache Prometheus metrics URL by running: 60 | 61 | kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ printf "%s-metrics" (include "common.names.fullname" .) }} {{ .Values.metrics.service.port }}:{{ .Values.metrics.service.port }} & 62 | echo "Apache Prometheus metrics URL: http://127.0.0.1:{{ .Values.metrics.service.port }}/metrics" 63 | 64 | 2. Open a browser and access Apache Prometheus metrics using the obtained URL. 65 | 66 | {{- end }} 67 | 68 | {{- include "common.warnings.rollingTag" .Values.image }} 69 | {{- include "common.warnings.rollingTag" .Values.metrics.image }} 70 | {{- $passwordValidationErrors := list -}} 71 | {{- if not .Values.existingSecret -}} 72 | {{- $secretName := include "wordpress.secretName" . -}} 73 | {{- $requiredWordPressPassword := dict "valueKey" "wordpressPassword" "secret" $secretName "field" "wordpress-password" "context" $ -}} 74 | {{- $requiredWordPressPasswordError := include "common.validations.values.single.empty" $requiredWordPressPassword -}} 75 | {{- $passwordValidationErrors = append $passwordValidationErrors $requiredWordPressPasswordError -}} 76 | {{- end }} 77 | {{- if .Values.mariadb.enabled }} 78 | {{- $mariadbSecretName := include "wordpress.databaseSecretName" . -}} 79 | {{- $mariadbPasswordValidationErrors := include "common.validations.values.mariadb.passwords" (dict "secret" $mariadbSecretName "subchart" true "context" $) -}} 80 | {{- $passwordValidationErrors = append $passwordValidationErrors $mariadbPasswordValidationErrors -}} 81 | {{- end }} 82 | {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $) -}} 83 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | 3 | {{/* 4 | Create a default fully qualified app name. 5 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 6 | */}} 7 | {{- define "wordpress.mariadb.fullname" -}} 8 | {{- printf "%s-%s" .Release.Name "mariadb" | trunc 63 | trimSuffix "-" -}} 9 | {{- end -}} 10 | 11 | {{/* 12 | Create a default fully qualified app name. 13 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 14 | */}} 15 | {{- define "wordpress.memcached.fullname" -}} 16 | {{- printf "%s-%s" .Release.Name "memcached" | trunc 63 | trimSuffix "-" -}} 17 | {{- end -}} 18 | 19 | {{/* 20 | Return the proper WordPress image name 21 | */}} 22 | {{- define "wordpress.image" -}} 23 | {{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) -}} 24 | {{- end -}} 25 | 26 | {{/* 27 | Return the proper image name (for the metrics image) 28 | */}} 29 | {{- define "wordpress.metrics.image" -}} 30 | {{- include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) -}} 31 | {{- end -}} 32 | 33 | {{/* 34 | Return the proper image name (for the init container volume-permissions image) 35 | */}} 36 | {{- define "wordpress.volumePermissions.image" -}} 37 | {{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}} 38 | {{- end -}} 39 | 40 | {{/* 41 | Return the proper Docker Image Registry Secret Names 42 | */}} 43 | {{- define "wordpress.imagePullSecrets" -}} 44 | {{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "global" .Values.global) -}} 45 | {{- end -}} 46 | 47 | {{/* 48 | Return the proper Storage Class 49 | */}} 50 | {{- define "wordpress.storageClass" -}} 51 | {{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) -}} 52 | {{- end -}} 53 | 54 | {{/* 55 | Create chart name and version as used by the chart label. 56 | */}} 57 | {{- define "wordpress.customHTAccessCM" -}} 58 | {{- printf "%s" .Values.customHTAccessCM -}} 59 | {{- end -}} 60 | 61 | {{/* 62 | Return the MariaDB Hostname 63 | */}} 64 | {{- define "wordpress.databaseHost" -}} 65 | {{- if .Values.mariadb.enabled }} 66 | {{- if eq .Values.mariadb.architecture "replication" }} 67 | {{- printf "%s-%s" (include "wordpress.mariadb.fullname" .) "primary" | trunc 63 | trimSuffix "-" -}} 68 | {{- else -}} 69 | {{- printf "%s" (include "wordpress.mariadb.fullname" .) -}} 70 | {{- end -}} 71 | {{- else -}} 72 | {{- printf "%s" .Values.externalDatabase.host -}} 73 | {{- end -}} 74 | {{- end -}} 75 | 76 | {{/* 77 | Return the MariaDB Port 78 | */}} 79 | {{- define "wordpress.databasePort" -}} 80 | {{- if .Values.mariadb.enabled }} 81 | {{- printf "3306" -}} 82 | {{- else -}} 83 | {{- printf "%d" (.Values.externalDatabase.port | int ) -}} 84 | {{- end -}} 85 | {{- end -}} 86 | 87 | {{/* 88 | Return the MariaDB Database Name 89 | */}} 90 | {{- define "wordpress.databaseName" -}} 91 | {{- if .Values.mariadb.enabled }} 92 | {{- printf "%s" .Values.mariadb.auth.database -}} 93 | {{- else -}} 94 | {{- printf "%s" .Values.externalDatabase.database -}} 95 | {{- end -}} 96 | {{- end -}} 97 | 98 | {{/* 99 | Return the MariaDB User 100 | */}} 101 | {{- define "wordpress.databaseUser" -}} 102 | {{- if .Values.mariadb.enabled }} 103 | {{- printf "%s" .Values.mariadb.auth.username -}} 104 | {{- else -}} 105 | {{- printf "%s" .Values.externalDatabase.user -}} 106 | {{- end -}} 107 | {{- end -}} 108 | 109 | {{/* 110 | Return the MariaDB Secret Name 111 | */}} 112 | {{- define "wordpress.databaseSecretName" -}} 113 | {{- if .Values.mariadb.enabled }} 114 | {{- if .Values.mariadb.auth.existingSecret -}} 115 | {{- printf "%s" .Values.mariadb.auth.existingSecret -}} 116 | {{- else -}} 117 | {{- printf "%s" (include "wordpress.mariadb.fullname" .) -}} 118 | {{- end -}} 119 | {{- else if .Values.externalDatabase.existingSecret -}} 120 | {{- printf "%s" .Values.externalDatabase.existingSecret -}} 121 | {{- else -}} 122 | {{- printf "%s-%s" (include "common.names.fullname" .) "externaldb" -}} 123 | {{- end -}} 124 | {{- end -}} 125 | 126 | {{/* 127 | Return the WordPress Secret Name 128 | */}} 129 | {{- define "wordpress.secretName" -}} 130 | {{- if .Values.existingSecret }} 131 | {{- printf "%s" .Values.existingSecret -}} 132 | {{- else -}} 133 | {{- printf "%s" (include "common.names.fullname" .) -}} 134 | {{- end -}} 135 | {{- end -}} 136 | 137 | {{/* 138 | Return the SMTP Secret Name 139 | */}} 140 | {{- define "wordpress.smtpSecretName" -}} 141 | {{- if .Values.smtpExistingSecret }} 142 | {{- printf "%s" .Values.smtpExistingSecret -}} 143 | {{- else -}} 144 | {{- printf "%s" (include "common.names.fullname" .) -}} 145 | {{- end -}} 146 | {{- end -}} 147 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "common.names.fullname" . }} 5 | labels: {{- include "common.labels.standard" . | nindent 4 }} 6 | {{- if .Values.commonLabels }} 7 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 8 | {{- end }} 9 | {{- if .Values.commonAnnotations }} 10 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 11 | {{- end }} 12 | spec: 13 | selector: 14 | matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} 15 | {{- if .Values.updateStrategy }} 16 | strategy: {{- toYaml .Values.updateStrategy | nindent 4 }} 17 | {{- end }} 18 | replicas: {{ .Values.replicaCount }} 19 | template: 20 | metadata: 21 | labels: {{- include "common.labels.standard" . | nindent 8 }} 22 | {{- if .Values.podLabels }} 23 | {{- include "common.tplvalues.render" (dict "value" .Values.podLabels "context" $) | nindent 8 }} 24 | {{- end }} 25 | {{- if or .Values.podAnnotations .Values.metrics.enabled }} 26 | annotations: 27 | {{- if .Values.podAnnotations }} 28 | {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} 29 | {{- end }} 30 | {{- if .Values.metrics.podAnnotations }} 31 | {{- include "common.tplvalues.render" (dict "value" .Values.metrics.podAnnotations "context" $) | nindent 8 }} 32 | {{- end }} 33 | {{- end }} 34 | spec: 35 | {{- include "wordpress.imagePullSecrets" . | nindent 6 }} 36 | {{- if .Values.schedulerName }} 37 | schedulerName: {{ .Values.schedulerName | quote }} 38 | {{- end }} 39 | serviceAccountName: {{ .Values.serviceAccountName }} 40 | {{- if .Values.hostAliases }} 41 | # yamllint disable rule:indentation 42 | hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} 43 | # yamllint enable rule:indentation 44 | {{- end }} 45 | {{- if .Values.affinity }} 46 | affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} 47 | {{- else }} 48 | affinity: 49 | podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "context" $) | nindent 10 }} 50 | podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "context" $) | nindent 10 }} 51 | nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} 52 | {{- end }} 53 | {{- if .Values.nodeSelector }} 54 | nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} 55 | {{- end }} 56 | {{- if .Values.tolerations }} 57 | tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} 58 | {{- end }} 59 | {{- if .Values.podSecurityContext.enabled }} 60 | securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} 61 | {{- end }} 62 | {{- if or (and .Values.podSecurityContext.enabled .Values.volumePermissions.enabled .Values.persistence.enabled) (.Values.initContainers) }} 63 | initContainers: 64 | {{- if and .Values.podSecurityContext.enabled .Values.volumePermissions.enabled .Values.persistence.enabled }} 65 | - name: volume-permissions 66 | image: "{{ template "wordpress.volumePermissions.image" . }}" 67 | imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} 68 | command: 69 | - /bin/sh 70 | - -cx 71 | - | 72 | {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} 73 | chown -R `id -u`:`id -G | cut -d " " -f2` /bitnami/wordpress 74 | {{- else }} 75 | chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} /bitnami/wordpress 76 | {{- end }} 77 | {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto "}} 78 | securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} 79 | {{- else }} 80 | securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} 81 | {{- end }} 82 | {{- if .Values.volumePermissions.resources }} 83 | resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} 84 | {{- end }} 85 | volumeMounts: 86 | - mountPath: /bitnami/wordpress 87 | name: wordpress-data 88 | subPath: wordpress 89 | {{- end }} 90 | {{- if .Values.initContainers }} 91 | {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} 92 | {{- end }} 93 | {{- end }} 94 | containers: 95 | - name: wordpress 96 | image: {{ template "wordpress.image" . }} 97 | imagePullPolicy: {{ .Values.image.pullPolicy | quote }} 98 | {{- if .Values.command }} 99 | command: {{- include "common.tplvalues.render" ( dict "value" .Values.command "context" $) | nindent 12 }} 100 | {{- end }} 101 | {{- if .Values.args }} 102 | args: {{- include "common.tplvalues.render" ( dict "value" .Values.args "context" $) | nindent 12 }} 103 | {{- end }} 104 | {{- if .Values.containerSecurityContext.enabled }} 105 | securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} 106 | {{- end }} 107 | env: 108 | {{- if .Values.image.debug }} 109 | - name: NAMI_DEBUG 110 | value: "--log-level trace" 111 | {{- end }} 112 | - name: ALLOW_EMPTY_PASSWORD 113 | value: {{ ternary "yes" "no" .Values.allowEmptyPassword | quote }} 114 | - name: MARIADB_HOST 115 | value: {{ include "wordpress.databaseHost" . | quote }} 116 | - name: MARIADB_PORT_NUMBER 117 | value: {{ include "wordpress.databasePort" . | quote }} 118 | - name: WORDPRESS_DATABASE_NAME 119 | value: {{ include "wordpress.databaseName" . | quote }} 120 | - name: WORDPRESS_DATABASE_USER 121 | value: {{ include "wordpress.databaseUser" . | quote }} 122 | - name: WORDPRESS_DATABASE_PASSWORD 123 | valueFrom: 124 | secretKeyRef: 125 | name: {{ include "wordpress.databaseSecretName" . }} 126 | key: mariadb-password 127 | - name: WORDPRESS_USERNAME 128 | value: {{ .Values.wordpressUsername | quote }} 129 | - name: WORDPRESS_PASSWORD 130 | valueFrom: 131 | secretKeyRef: 132 | name: {{ include "wordpress.secretName" . }} 133 | key: wordpress-password 134 | - name: WORDPRESS_EMAIL 135 | value: {{ .Values.wordpressEmail | quote }} 136 | - name: WORDPRESS_FIRST_NAME 137 | value: {{ .Values.wordpressFirstName | quote }} 138 | - name: WORDPRESS_LAST_NAME 139 | value: {{ .Values.wordpressLastName | quote }} 140 | - name: WORDPRESS_HTACCESS_OVERRIDE_NONE 141 | value: {{ ternary "yes" "no" .Values.allowOverrideNone | quote }} 142 | - name: WORDPRESS_HTACCESS_PERSISTENCE_ENABLED 143 | value: {{ ternary "yes" "no" .Values.htaccessPersistenceEnabled | quote }} 144 | - name: WORDPRESS_BLOG_NAME 145 | value: {{ .Values.wordpressBlogName | quote }} 146 | - name: WORDPRESS_SKIP_INSTALL 147 | value: {{ ternary "yes" "no" .Values.wordpressSkipInstall | quote }} 148 | - name: WORDPRESS_TABLE_PREFIX 149 | value: {{ .Values.wordpressTablePrefix | quote }} 150 | - name: WORDPRESS_SCHEME 151 | value: {{ .Values.wordpressScheme | quote }} 152 | - name: WORDPRESS_EXTRA_WP_CONFIG_CONTENT 153 | value: {{ .Values.wordpressExtraConfigContent | quote }} 154 | {{- if .Values.smtpHost }} 155 | - name: SMTP_HOST 156 | value: {{ .Values.smtpHost | quote }} 157 | {{- end }} 158 | {{- if .Values.smtpPort }} 159 | - name: SMTP_PORT 160 | value: {{ .Values.smtpPort | quote }} 161 | {{- end }} 162 | {{- if .Values.smtpUser }} 163 | - name: SMTP_USER 164 | value: {{ .Values.smtpUser | quote }} 165 | {{- end }} 166 | {{- if or .Values.smtpPassword .Values.smtpExistingSecret }} 167 | - name: SMTP_PASSWORD 168 | valueFrom: 169 | secretKeyRef: 170 | name: {{ include "wordpress.smtpSecretName" . }} 171 | key: smtp-password 172 | {{- end }} 173 | {{- if .Values.smtpProtocol }} 174 | - name: SMTP_PROTOCOL 175 | value: {{ .Values.smtpProtocol | quote }} 176 | {{- end }} 177 | {{- if .Values.extraEnvVars }} 178 | {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} 179 | {{- end }} 180 | envFrom: 181 | {{- if .Values.extraEnvVarsCM }} 182 | - configMapRef: 183 | name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }} 184 | {{- end }} 185 | {{- if .Values.extraEnvVarsSecret }} 186 | - secretRef: 187 | name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} 188 | {{- end }} 189 | ports: 190 | - name: http 191 | containerPort: {{ .Values.containerPorts.http }} 192 | - name: https 193 | containerPort: {{ .Values.containerPorts.https }} 194 | {{- if .Values.livenessProbe.enabled }} 195 | livenessProbe: {{- omit .Values.livenessProbe "enabled" | toYaml | nindent 12 }} 196 | {{- else if .Values.customLivenessProbe }} 197 | livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} 198 | {{- end }} 199 | {{- if .Values.readinessProbe.enabled }} 200 | readinessProbe: {{- omit .Values.readinessProbe "enabled" | toYaml | nindent 12 }} 201 | {{- else if .Values.customReadinessProbe }} 202 | readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} 203 | {{- end }} 204 | {{- if .Values.resources }} 205 | resources: {{- toYaml .Values.resources | nindent 12 }} 206 | {{- end }} 207 | volumeMounts: 208 | - mountPath: /bitnami/wordpress 209 | name: wordpress-data 210 | subPath: wordpress 211 | {{- if and .Values.allowOverrideNone .Values.customHTAccessCM }} 212 | - mountPath: /htaccess 213 | name: custom-htaccess 214 | {{- end }} 215 | {{- if or .Values.customPostInitScripts .Values.memcached.enabled }} 216 | - mountPath: /docker-entrypoint-init.d 217 | name: custom-postinit 218 | {{- end }} 219 | {{- if .Values.extraVolumeMounts }} 220 | {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} 221 | {{- end }} 222 | {{- if .Values.metrics.enabled }} 223 | - name: metrics 224 | image: {{ template "wordpress.metrics.image" . }} 225 | imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} 226 | command: 227 | - /bin/apache_exporter 228 | - --scrape_uri 229 | - http://status.localhost:8080/server-status/?auto 230 | ports: 231 | - name: metrics 232 | containerPort: 9117 233 | livenessProbe: 234 | httpGet: 235 | path: /metrics 236 | port: metrics 237 | initialDelaySeconds: 15 238 | timeoutSeconds: 5 239 | readinessProbe: 240 | httpGet: 241 | path: /metrics 242 | port: metrics 243 | initialDelaySeconds: 5 244 | timeoutSeconds: 1 245 | {{- if .Values.metrics.resources }} 246 | resources: {{- toYaml .Values.metrics.resources | nindent 12 }} 247 | {{- end }} 248 | {{- end }} 249 | {{- if .Values.sidecars }} 250 | {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} 251 | {{- end }} 252 | volumes: 253 | {{- if and .Values.allowOverrideNone .Values.customHTAccessCM }} 254 | - name: custom-htaccess 255 | configMap: 256 | name: {{ template "wordpress.customHTAccessCM" . }} 257 | items: 258 | - key: wordpress-htaccess.conf 259 | path: wordpress-htaccess.conf 260 | {{- end }} 261 | {{- if or .Values.customPostInitScripts .Values.memcached.enabled }} 262 | - name: custom-postinit 263 | configMap: 264 | name: {{ printf "%s-postinit" (include "common.names.fullname" .) }} 265 | defaultMode: 0755 266 | {{- end }} 267 | - name: wordpress-data 268 | {{- if .Values.persistence.enabled }} 269 | persistentVolumeClaim: 270 | claimName: {{ .Values.persistence.existingClaim | default (include "common.names.fullname" .) }} 271 | {{- else }} 272 | emptyDir: {} 273 | {{ end }} 274 | {{- if .Values.extraVolumes }} 275 | {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} 276 | {{- end }} 277 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/externaldb-secrets.yaml: -------------------------------------------------------------------------------- 1 | {{- if not (or .Values.mariadb.enabled .Values.externalDatabase.existingSecret) }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ printf "%s-externaldb" (include "common.names.fullname" .) }} 6 | labels: {{- include "common.labels.standard" . | nindent 4 }} 7 | {{- if .Values.commonLabels }} 8 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 9 | {{- end }} 10 | {{- if .Values.commonAnnotations }} 11 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 12 | {{- end }} 13 | type: Opaque 14 | data: 15 | mariadb-password: {{ .Values.externalDatabase.password | b64enc | quote }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/extra-list.yaml: -------------------------------------------------------------------------------- 1 | {{- range .Values.extraDeploy }} 2 | --- 3 | {{ include "common.tplvalues.render" (dict "value" . "context" $) }} 4 | {{- end }} 5 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ template "common.names.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: {{- include "common.labels.standard" . | nindent 4 }} 8 | {{- if .Values.commonLabels }} 9 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 10 | {{- end }} 11 | {{- if .Values.commonAnnotations }} 12 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 13 | {{- end }} 14 | spec: 15 | scaleTargetRef: 16 | apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} 17 | kind: Deployment 18 | name: {{ template "common.names.fullname" . }} 19 | minReplicas: {{ .Values.autoscaling.minReplicas }} 20 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 21 | metrics: 22 | {{- if .Values.autoscaling.targetCPU }} 23 | - type: Resource 24 | resource: 25 | name: cpu 26 | targetAverageUtilization: {{ .Values.autoscaling.targetCPU }} 27 | {{- end }} 28 | {{- if .Values.autoscaling.targetMemory }} 29 | - type: Resource 30 | resource: 31 | name: memory 32 | targetAverageUtilization: {{ .Values.autoscaling.targetMemory }} 33 | {{- end }} 34 | {{- end }} 35 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled }} 2 | apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} 3 | kind: Ingress 4 | metadata: 5 | name: {{ include "common.names.fullname" . }} 6 | labels: {{- include "common.labels.standard" . | nindent 4 }} 7 | {{- if .Values.commonLabels }} 8 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 9 | {{- end }} 10 | annotations: 11 | {{- if .Values.ingress.certManager }} 12 | kubernetes.io/tls-acme: "true" 13 | {{- end }} 14 | {{- if .Values.ingress.annotations }} 15 | {{- include "common.tplvalues.render" (dict "value" .Values.ingress.annotations "context" $) | nindent 4 }} 16 | {{- end }} 17 | {{- if .Values.commonAnnotations }} 18 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 19 | {{- end }} 20 | spec: 21 | rules: 22 | {{- if .Values.ingress.hostname }} 23 | - host: {{ .Values.ingress.hostname | quote }} 24 | http: 25 | paths: 26 | {{- if .Values.ingress.extraPaths }} 27 | {{- toYaml .Values.ingress.extraPaths | nindent 10 }} 28 | {{- end }} 29 | - path: {{ .Values.ingress.path }} 30 | {{- if eq "true" (include "common.ingress.supportsPathType" .) }} 31 | pathType: {{ .Values.ingress.pathType }} 32 | {{- end }} 33 | backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "http" "context" $) | nindent 14 }} 34 | {{- end }} 35 | {{- range .Values.ingress.extraHosts }} 36 | - host: {{ .name | quote }} 37 | http: 38 | paths: 39 | - path: {{ default "/" .path }} 40 | {{- if eq "true" (include "common.ingress.supportsPathType" $) }} 41 | pathType: {{ default "ImplementationSpecific" .pathType }} 42 | {{- end }} 43 | backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} 44 | {{- end }} 45 | {{- if or .Values.ingress.tls .Values.ingress.extraTls }} 46 | tls: 47 | {{- if .Values.ingress.tls }} 48 | - hosts: 49 | - {{ .Values.ingress.hostname | quote }} 50 | {{- range .Values.ingress.extraHosts }} 51 | - {{ .name | quote }} 52 | {{- end }} 53 | secretName: {{ printf "%s-tls" .Values.ingress.hostname }} 54 | {{- end }} 55 | {{- if .Values.ingress.extraTls }} 56 | {{- include "common.tplvalues.render" ( dict "value" .Values.ingress.extraTls "context" $ ) | nindent 4 }} 57 | {{- end }} 58 | {{- end }} 59 | {{- end }} 60 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/metrics-svc.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.enabled }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: {{- include "common.labels.standard" . | nindent 4 }} 8 | app.kubernetes.io/component: metrics 9 | {{- if .Values.commonLabels }} 10 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 11 | {{- end }} 12 | {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} 13 | annotations: 14 | {{- if .Values.metrics.service.annotations }} 15 | {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.service.annotations "context" $ ) | nindent 4 }} 16 | {{- end }} 17 | {{- if .Values.commonAnnotations }} 18 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 19 | {{- end }} 20 | {{- end }} 21 | spec: 22 | type: ClusterIP 23 | ports: 24 | - name: metrics 25 | port: {{ .Values.metrics.service.port }} 26 | protocol: TCP 27 | targetPort: metrics 28 | selector: {{- include "common.labels.matchLabels" . | nindent 4 }} 29 | {{- end }} 30 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/pdb.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.pdb.create }} 2 | apiVersion: policy/v1beta1 3 | kind: PodDisruptionBudget 4 | metadata: 5 | name: {{ template "common.names.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: {{- include "common.labels.standard" . | nindent 4 }} 8 | {{- if .Values.commonLabels }} 9 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 10 | {{- end }} 11 | {{- if .Values.commonAnnotations }} 12 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 13 | {{- end }} 14 | spec: 15 | {{- if .Values.pdb.minAvailable }} 16 | minAvailable: {{ .Values.pdb.minAvailable }} 17 | {{- end }} 18 | {{- if .Values.pdb.maxUnavailable }} 19 | maxUnavailable: {{ .Values.pdb.maxUnavailable }} 20 | {{- end }} 21 | selector: 22 | matchLabels: {{ include "common.labels.matchLabels" . | nindent 6 }} 23 | {{- end }} 24 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/postinit-configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if or .Values.customPostInitScripts .Values.memcached.enabled }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ printf "%s-postinit" (include "common.names.fullname" .) }} 6 | data: 7 | {{- if .Values.memcached.enabled }} 8 | {{- $memcachedFullname := include "wordpress.memcached.fullname" . }} 9 | {{- $memcachedPort := int .Values.memcached.service.port }} 10 | {{- $releaseNamespace := .Release.Namespace }} 11 | {{- $clusterDomain := .Values.clusterDomain }} 12 | 00-configure-w3-total-cache.sh: |- 13 | #!/bin/bash 14 | 15 | # Add permisions to edit wp-config.php 16 | chmod +w /bitnami/wordpress/wp-config.php 17 | 18 | # Activate W3 Total Cache pairs 19 | wp plugin activate w3-total-cache 20 | wp total-cache fix_environment 21 | 22 | # Choose 'Memcached' as database cache method 23 | wp total-cache option set dbcache.engine memcached --type=string 24 | wp total-cache flush all 25 | wp total-cache option set dbcache.memcached.servers {{ $memcachedFullname }}.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $memcachedPort }} --type=string 26 | wp total-cache option set dbcache.enabled true --type=boolean 27 | wp total-cache flush all 28 | 29 | # Revoke permisions to edit wp-config.php 30 | chmod -w bitnami/wordpress/wp-config.php 31 | {{- end }} 32 | {{- if .Values.customPostInitScripts }} 33 | {{- include "common.tplvalues.render" (dict "value" .Values.customPostInitScripts "context" $) | nindent 2 }} 34 | {{- end }} 35 | {{- end }} 36 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} 2 | kind: PersistentVolumeClaim 3 | apiVersion: v1 4 | metadata: 5 | name: {{ include "common.names.fullname" . }} 6 | labels: {{- include "common.labels.standard" . | nindent 4 }} 7 | {{- if .Values.commonLabels }} 8 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 9 | {{- end }} 10 | {{- if .Values.commonAnnotations }} 11 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 12 | {{- end }} 13 | spec: 14 | accessModes: 15 | {{- if not (empty .Values.persistence.accessModes) }} 16 | {{- range .Values.persistence.accessModes }} 17 | - {{ . | quote }} 18 | {{- end }} 19 | {{- else }} 20 | - {{ .Values.persistence.accessMode | quote }} 21 | {{- end }} 22 | resources: 23 | requests: 24 | storage: {{ .Values.persistence.size | quote }} 25 | {{- include "wordpress.storageClass" . | nindent 2 }} 26 | {{- if .Values.persistence.dataSource }} 27 | dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.dataSource "context" $) | nindent 4 }} 28 | {{- end }} 29 | {{- end }} 30 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/secrets.yaml: -------------------------------------------------------------------------------- 1 | {{- if or (not .Values.existingSecret) (and (not .Values.smtpExistingSecret) .Values.smtpPassword) }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "common.names.fullname" . }} 6 | labels: {{- include "common.labels.standard" . | nindent 4 }} 7 | {{- if .Values.commonLabels }} 8 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 9 | {{- end }} 10 | {{- if .Values.commonAnnotations }} 11 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 12 | {{- end }} 13 | type: Opaque 14 | data: 15 | {{- if not .Values.existingSecret }} 16 | {{- if .Values.wordpressPassword }} 17 | wordpress-password: {{ .Values.wordpressPassword | b64enc | quote }} 18 | {{- else }} 19 | wordpress-password: {{ randAlphaNum 10 | b64enc | quote }} 20 | {{- end }} 21 | {{- end }} 22 | {{- if and .Values.smtpPassword (not .Values.smtpExistingSecret) }} 23 | {{- if .Values.smtpPassword }} 24 | smtp-password: {{ .Values.smtpPassword | b64enc | quote }} 25 | {{- end }} 26 | {{- end }} 27 | {{- end }} 28 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | name: {{ include "common.names.fullname" . }} 6 | {{- if .Values.metrics.serviceMonitor.namespace }} 7 | namespace: {{ .Values.metrics.serviceMonitor.namespace }} 8 | {{- end }} 9 | labels: {{- include "common.labels.standard" . | nindent 4 }} 10 | app.kubernetes.io/component: metrics 11 | {{- if .Values.metrics.serviceMonitor.additionalLabels }} 12 | {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.additionalLabels "context" $) | nindent 4 }} 13 | {{- end }} 14 | {{- if .Values.commonLabels }} 15 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 16 | {{- end }} 17 | {{- if .Values.commonAnnotations }} 18 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 19 | {{- end }} 20 | spec: 21 | endpoints: 22 | - port: metrics 23 | interval: {{ .Values.metrics.serviceMonitor.interval }} 24 | {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} 25 | scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} 26 | {{- end }} 27 | honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} 28 | {{- if .Values.metrics.serviceMonitor.relabellings }} 29 | metricRelabelings: {{- toYaml .Values.metrics.serviceMonitor.relabellings | nindent 8 }} 30 | {{- end }} 31 | namespaceSelector: 32 | matchNames: 33 | - {{ .Release.Namespace }} 34 | selector: 35 | matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} 36 | app.kubernetes.io/component: metrics 37 | {{- end }} 38 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "common.names.fullname" . }} 5 | labels: {{- include "common.labels.standard" . | nindent 4 }} 6 | {{- if .Values.commonLabels }} 7 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 8 | {{- end }} 9 | {{- if or .Values.service.annotations .Values.commonAnnotations }} 10 | annotations: 11 | {{- if .Values.service.annotations }} 12 | {{- include "common.tplvalues.render" (dict "value" .Values.service.annotations "context" $) | nindent 4 }} 13 | {{- end }} 14 | {{- if .Values.commonAnnotations }} 15 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | spec: 19 | type: {{ .Values.service.type }} 20 | {{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }} 21 | clusterIP: {{ .Values.service.clusterIP }} 22 | {{- end }} 23 | {{- if (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) }} 24 | externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} 25 | {{- end }} 26 | {{- if (and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges) }} 27 | loadBalancerSourceRanges: {{- toYaml . | nindent 4 }} 28 | {{- end }} 29 | {{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP))) }} 30 | loadBalancerIP: {{ .Values.service.loadBalancerIP }} 31 | {{- end }} 32 | ports: 33 | - name: http 34 | port: {{ .Values.service.port }} 35 | protocol: TCP 36 | targetPort: http 37 | {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.http))) }} 38 | nodePort: {{ .Values.service.nodePorts.http }} 39 | {{- else if eq .Values.service.type "ClusterIP" }} 40 | nodePort: null 41 | {{- end }} 42 | - name: https 43 | port: {{ .Values.service.httpsPort }} 44 | protocol: TCP 45 | targetPort: {{ .Values.service.httpsTargetPort }} 46 | {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.https))) }} 47 | nodePort: {{ .Values.service.nodePorts.https }} 48 | {{- else if eq .Values.service.type "ClusterIP" }} 49 | nodePort: null 50 | {{- end }} 51 | {{- if .Values.service.extraPorts }} 52 | {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} 53 | {{- end }} 54 | selector: {{- include "common.labels.matchLabels" . | nindent 4 }} 55 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/tests/test-mariadb-connection.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.mariadb.enabled }} 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: "{{ .Release.Name }}-credentials-test" 6 | annotations: 7 | "helm.sh/hook": test-success 8 | spec: 9 | {{- if .Values.podSecurityContext.enabled }} 10 | securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 4 }} 11 | {{- end }} 12 | containers: 13 | - name: {{ .Release.Name }}-credentials-test 14 | image: {{ template "wordpress.image" . }} 15 | imagePullPolicy: {{ .Values.image.pullPolicy | quote }} 16 | {{- if .Values.containerSecurityContext.enabled }} 17 | securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 8 }} 18 | {{- end }} 19 | env: 20 | - name: MARIADB_HOST 21 | value: {{ include "wordpress.databaseHost" . | quote }} 22 | - name: MARIADB_PORT 23 | value: "3306" 24 | - name: WORDPRESS_DATABASE_NAME 25 | value: {{ default "" .Values.mariadb.auth.database | quote }} 26 | - name: WORDPRESS_DATABASE_USER 27 | value: {{ default "" .Values.mariadb.auth.username | quote }} 28 | - name: WORDPRESS_DATABASE_PASSWORD 29 | valueFrom: 30 | secretKeyRef: 31 | name: {{ include "wordpress.databaseSecretName" . }} 32 | key: mariadb-password 33 | command: 34 | - /bin/bash 35 | - -ec 36 | - | 37 | mysql --host=$MARIADB_HOST --port=$MARIADB_PORT --user=$WORDPRESS_DATABASE_USER --password=$WORDPRESS_DATABASE_PASSWORD 38 | restartPolicy: Never 39 | {{- end }} 40 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/templates/tls-secrets.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled }} 2 | {{- if .Values.ingress.secrets }} 3 | {{- range .Values.ingress.secrets }} 4 | apiVersion: v1 5 | kind: Secret 6 | metadata: 7 | name: {{ .name }} 8 | namespace: {{ $.Release.Namespace }} 9 | labels: {{- include "common.labels.standard" $ | nindent 4 }} 10 | {{- if $.Values.commonLabels }} 11 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 12 | {{- end }} 13 | {{- if $.Values.commonAnnotations }} 14 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 15 | {{- end }} 16 | type: kubernetes.io/tls 17 | data: 18 | tls.crt: {{ .certificate | b64enc }} 19 | tls.key: {{ .key | b64enc }} 20 | --- 21 | {{- end }} 22 | {{- end }} 23 | {{- if and .Values.ingress.tls (not .Values.ingress.certManager) }} 24 | {{- $ca := genCA "wordpress-ca" 365 }} 25 | {{- $cert := genSignedCert .Values.ingress.hostname nil (list .Values.ingress.hostname) 365 $ca }} 26 | apiVersion: v1 27 | kind: Secret 28 | metadata: 29 | name: {{ printf "%s-tls" .Values.ingress.hostname }} 30 | namespace: {{ .Release.Namespace }} 31 | labels: {{- include "common.labels.standard" . | nindent 4 }} 32 | {{- if .Values.commonLabels }} 33 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 34 | {{- end }} 35 | {{- if .Values.commonAnnotations }} 36 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 37 | {{- end }} 38 | type: kubernetes.io/tls 39 | data: 40 | tls.crt: {{ $cert.Cert | b64enc | quote }} 41 | tls.key: {{ $cert.Key | b64enc | quote }} 42 | ca.crt: {{ $ca.Cert | b64enc | quote }} 43 | {{- end }} 44 | {{- end }} 45 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/values.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema#", 3 | "type": "object", 4 | "properties": { 5 | "wordpressUsername": { 6 | "type": "string", 7 | "title": "Username", 8 | "form": true 9 | }, 10 | "wordpressPassword": { 11 | "type": "string", 12 | "title": "Password", 13 | "form": true, 14 | "description": "Defaults to a random 10-character alphanumeric string if not set" 15 | }, 16 | "wordpressEmail": { 17 | "type": "string", 18 | "title": "Admin email", 19 | "form": true 20 | }, 21 | "wordpressBlogName": { 22 | "type": "string", 23 | "title": "Blog Name", 24 | "form": true 25 | }, 26 | "persistence": { 27 | "type": "object", 28 | "properties": { 29 | "size": { 30 | "type": "string", 31 | "title": "Persistent Volume Size", 32 | "form": true, 33 | "render": "slider", 34 | "sliderMin": 1, 35 | "sliderMax": 100, 36 | "sliderUnit": "Gi" 37 | } 38 | } 39 | }, 40 | "mariadb": { 41 | "type": "object", 42 | "title": "MariaDB Details", 43 | "form": true, 44 | "properties": { 45 | "enabled": { 46 | "type": "boolean", 47 | "title": "Use a new MariaDB database hosted in the cluster", 48 | "form": true, 49 | "description": "Whether to deploy a mariadb server to satisfy the applications database requirements. To use an external database switch this off and configure the external database details" 50 | }, 51 | "primary": { 52 | "type": "object", 53 | "properties": { 54 | "persistence": { 55 | "type": "object", 56 | "properties": { 57 | "size": { 58 | "type": "string", 59 | "title": "Volume Size", 60 | "form": true, 61 | "hidden": { 62 | "value": false, 63 | "path": "mariadb/enabled" 64 | }, 65 | "render": "slider", 66 | "sliderMin": 1, 67 | "sliderMax": 100, 68 | "sliderUnit": "Gi" 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | }, 76 | "externalDatabase": { 77 | "type": "object", 78 | "title": "External Database Details", 79 | "description": "If MariaDB is disabled. Use this section to specify the external database details", 80 | "form": true, 81 | "properties": { 82 | "host": { 83 | "type": "string", 84 | "form": true, 85 | "title": "Database Host", 86 | "hidden": "mariadb/enabled" 87 | }, 88 | "user": { 89 | "type": "string", 90 | "form": true, 91 | "title": "Database Username", 92 | "hidden": "mariadb/enabled" 93 | }, 94 | "password": { 95 | "type": "string", 96 | "form": true, 97 | "title": "Database Password", 98 | "hidden": "mariadb/enabled" 99 | }, 100 | "database": { 101 | "type": "string", 102 | "form": true, 103 | "title": "Database Name", 104 | "hidden": "mariadb/enabled" 105 | }, 106 | "port": { 107 | "type": "integer", 108 | "form": true, 109 | "title": "Database Port", 110 | "hidden": "mariadb/enabled" 111 | } 112 | } 113 | }, 114 | "ingress": { 115 | "type": "object", 116 | "form": true, 117 | "title": "Ingress Configuration", 118 | "properties": { 119 | "enabled": { 120 | "type": "boolean", 121 | "form": true, 122 | "title": "Use a custom hostname", 123 | "description": "Enable the ingress resource that allows you to access the WordPress installation." 124 | }, 125 | "hostname": { 126 | "type": "string", 127 | "form": true, 128 | "title": "Hostname", 129 | "hidden": { 130 | "value": false, 131 | "path": "ingress/enabled" 132 | } 133 | }, 134 | "certManager": { 135 | "type": "boolean", 136 | "form": true, 137 | "title": "Enable CertManager", 138 | "description": "This will add the required annotation for CertManager to add certificates.", 139 | "hidden": { 140 | "value": false, 141 | "path": "ingress/enabled" 142 | } 143 | }, 144 | "tls": { 145 | "type": "boolean", 146 | "form": true, 147 | "title": "Create a TLS secret", 148 | "hidden": { 149 | "value": false, 150 | "path": "ingress/enabled" 151 | } 152 | } 153 | } 154 | }, 155 | "service": { 156 | "type": "object", 157 | "form": true, 158 | "title": "Service Configuration", 159 | "properties": { 160 | "type": { 161 | "type": "string", 162 | "form": true, 163 | "title": "Service Type", 164 | "description": "Allowed values: \"ClusterIP\", \"NodePort\" and \"LoadBalancer\"" 165 | } 166 | } 167 | }, 168 | "resources": { 169 | "type": "object", 170 | "title": "Required Resources", 171 | "description": "Configure resource requests", 172 | "form": true, 173 | "properties": { 174 | "requests": { 175 | "type": "object", 176 | "properties": { 177 | "memory": { 178 | "type": "string", 179 | "form": true, 180 | "render": "slider", 181 | "title": "Memory Request", 182 | "sliderMin": 10, 183 | "sliderMax": 2048, 184 | "sliderUnit": "Mi" 185 | }, 186 | "cpu": { 187 | "type": "string", 188 | "form": true, 189 | "render": "slider", 190 | "title": "CPU Request", 191 | "sliderMin": 10, 192 | "sliderMax": 2000, 193 | "sliderUnit": "m" 194 | } 195 | } 196 | } 197 | } 198 | }, 199 | "volumePermissions": { 200 | "type": "object", 201 | "properties": { 202 | "enabled": { 203 | "type": "boolean", 204 | "form": true, 205 | "title": "Enable Init Containers", 206 | "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" 207 | } 208 | } 209 | }, 210 | "metrics": { 211 | "type": "object", 212 | "properties": { 213 | "enabled": { 214 | "type": "boolean", 215 | "title": "Enable Metrics", 216 | "description": "Prometheus Exporter / Metrics", 217 | "form": true 218 | } 219 | } 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /Chapter17/01_helm/bitnami/wordpress/values.yaml: -------------------------------------------------------------------------------- 1 | ## Global Docker image parameters 2 | ## Please, note that this will override the image parameters, including dependencies, configured to use the global value 3 | ## Current available global Docker image parameters: imageRegistry and imagePullSecrets 4 | ## 5 | # global: 6 | # imageRegistry: myRegistryName 7 | # imagePullSecrets: 8 | # - myRegistryKeySecretName 9 | # storageClass: myStorageClass 10 | 11 | ## Bitnami WordPress image version 12 | ## ref: https://hub.docker.com/r/bitnami/wordpress/tags/ 13 | ## 14 | image: 15 | registry: docker.io 16 | repository: bitnami/wordpress 17 | tag: 5.7.0-debian-10-r9 18 | ## Specify a imagePullPolicy 19 | ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' 20 | ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images 21 | ## 22 | pullPolicy: IfNotPresent 23 | ## Optionally specify an array of imagePullSecrets. 24 | ## Secrets must be manually created in the namespace. 25 | ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ 26 | ## e.g: 27 | ## pullSecrets: 28 | ## - myRegistryKeySecretName 29 | ## 30 | pullSecrets: [] 31 | ## Set to true if you would like to see extra information on logs 32 | ## 33 | debug: false 34 | 35 | ## String to partially override common.names.fullname template (will maintain the release name) 36 | ## 37 | # nameOverride: 38 | 39 | ## String to fully override common.names.fullname template 40 | ## 41 | # fullnameOverride: 42 | 43 | ## Add labels to all the deployed resources 44 | ## 45 | commonLabels: {} 46 | 47 | ## Add annotations to all the deployed resources 48 | ## 49 | commonAnnotations: {} 50 | 51 | ## Force target Kubernetes version (using Helm capabilites if not set) 52 | ## 53 | kubeVersion: 54 | 55 | ## Kubernetes Cluster Domain 56 | ## 57 | clusterDomain: cluster.local 58 | 59 | ## Extra objects to deploy (value evaluated as a template) 60 | ## 61 | extraDeploy: [] 62 | 63 | ## Use a service account for the WordPress pod 64 | ## 65 | serviceAccountName: default 66 | 67 | ## WordPress username 68 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 69 | ## 70 | wordpressUsername: user 71 | 72 | ## WordPress user password 73 | ## Defaults to a random 10-character alphanumeric string if not set 74 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 75 | ## 76 | wordpressPassword: "" 77 | 78 | ## Use existing secret (does not create the WordPress Secret object) 79 | ## NOTE: Must contain key `wordpress-password` 80 | ## NOTE: When it's set, the `wordpressPassword` parameter is ignored 81 | ## 82 | # existingSecret: 83 | 84 | ## WordPress user email 85 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 86 | ## 87 | wordpressEmail: user@example.com 88 | 89 | ## WordPress user first name 90 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 91 | ## 92 | wordpressFirstName: FirstName 93 | 94 | ## WordPress user last name 95 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 96 | ## 97 | wordpressLastName: LastName 98 | 99 | ## Blog name 100 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 101 | ## 102 | wordpressBlogName: User's Blog! 103 | 104 | ## Table prefix 105 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 106 | ## 107 | wordpressTablePrefix: wp_ 108 | 109 | ## Scheme to generate application URLs 110 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 111 | ## 112 | wordpressScheme: http 113 | 114 | ## Skip wizard installation (recommended if you use an external database that already contains WordPress data) 115 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#connect-wordpress-docker-container-to-an-existing-database 116 | ## 117 | wordpressSkipInstall: false 118 | 119 | ## Add extra content to the default configuration file 120 | ## e.g: 121 | ## wordpressExtraConfigContent: | 122 | ## @ini_set( 'post_max_size', '128M'); 123 | ## @ini_set( 'memory_limit', '256M' ); 124 | ## 125 | wordpressExtraConfigContent: "" 126 | 127 | ## Make use of custom post-init.d user scripts functionality inside the bitnami/wordpress image 128 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress/tree/master/5/debian-10/rootfs/post-init.d 129 | ## 130 | ## The logic of the post-init.d user scripts is that all is all files with extensions .sh, .sql or .php are executed for one time only, at the very first initialization of the pod as the very last step of entrypoint.sh. 131 | ## e.g: 132 | ## customPostInitScripts: 133 | ## enable-multisite.sh: | 134 | ## #!/bin/bash 135 | ## chmod +w /bitnami/wordpress/wp-config.php 136 | ## wp core multisite-install --url=example.com --title="Welcome to the WordPress Multisite" --admin_user="doesntmatternotreallyused" --admin_password="doesntmatternotreallyused" --admin_email="user@example.com" 137 | ## cat /docker-entrypoint-init.d/.htaccess > /bitnami/wordpress/.htaccess 138 | ## chmod -w bitnami/wordpress/wp-config.php 139 | ## .htaccess: | 140 | ## RewriteEngine On 141 | ## RewriteBase / 142 | ## ... 143 | ## 144 | ## NOTE: Combined with extraVolume and extraVolumeMounts to mount the configmap to /docker-entrypoint-init.d where custom user init scripts are looked for 145 | ## 146 | customPostInitScripts: {} 147 | 148 | ## SMTP mail delivery configuration 149 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress/#smtp-configuration 150 | ## 151 | # smtpHost: 152 | # smtpPort: 153 | # smtpUser: 154 | # smtpPassword: 155 | # smtpProtocol: 156 | 157 | ## Use an existing secret for the SMTP Password 158 | ## Can be the same secret as existingSecret 159 | ## Must contain key `smtp-password` 160 | ## NOTE: When it's set, the `smtpPassword` parameter is ignored 161 | ## 162 | # smtpExistingSecret: 163 | 164 | ## Set to `false` to allow the container to be started with blank passwords 165 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 166 | ## 167 | allowEmptyPassword: true 168 | 169 | ## Set Apache allowOverride to None 170 | ## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables 171 | ## 172 | allowOverrideNone: false 173 | 174 | ## Persist the custom changes of the htaccess. 175 | ## If `allowOverrideNone` is `true`, it will persist `/opt/bitnami/wordpress/wordpress-htaccess.conf` 176 | ## If `allowOverrideNone` is `false`, it will persist `/opt/bitnami/wordpress/.htaccess` 177 | ## 178 | htaccessPersistenceEnabled: false 179 | 180 | ## Existing ConfigMap with containing a custom wordpress-htaccess.conf file (requires `allowOverrideNone=true`) 181 | ## 182 | customHTAccessCM: "" 183 | 184 | ## Command and args for running the container (set to default if not set). Use array form 185 | ## 186 | command: [] 187 | args: [] 188 | 189 | ## An array to add extra env vars 190 | ## e.g: 191 | ## extraEnvVars: 192 | ## - name: FOO 193 | ## value: "bar" 194 | ## 195 | extraEnvVars: [] 196 | 197 | ## ConfigMap with extra environment variables 198 | ## 199 | extraEnvVarsCM: 200 | 201 | ## Secret with extra environment variables 202 | ## 203 | extraEnvVarsSecret: 204 | 205 | ## Number of replicas (requires ReadWriteMany PVC support) 206 | ## 207 | replicaCount: 1 208 | 209 | ## Set up update strategy for wordpress installation. Set to Recreate if you use persistent volume that cannot be mounted by more than one pods to makesure the pods is destroyed first. 210 | ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy 211 | ## e.g: 212 | ## updateStrategy: 213 | ## type: RollingUpdate 214 | ## rollingUpdate: 215 | ## maxSurge: 25% 216 | ## maxUnavailable: 25% 217 | ## 218 | updateStrategy: 219 | type: RollingUpdate 220 | 221 | ## Use an alternate scheduler, e.g. "stork". 222 | ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ 223 | ## 224 | # schedulerName: 225 | 226 | ## WordPress pod host aliases 227 | ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ 228 | ## 229 | hostAliases: 230 | ## Required for apache-exporter to work 231 | - ip: "127.0.0.1" 232 | hostnames: 233 | - "status.localhost" 234 | 235 | ## Extra volumes to add to the deployment 236 | ## 237 | extraVolumes: [] 238 | 239 | ## Extra volume mounts to add to the container 240 | ## 241 | extraVolumeMounts: [] 242 | 243 | ## Add sidecars to the pod. 244 | ## e.g: 245 | ## sidecars: 246 | ## - name: your-image-name 247 | ## image: your-image 248 | ## imagePullPolicy: Always 249 | ## ports: 250 | ## - name: portname 251 | ## containerPort: 1234 252 | ## 253 | sidecars: {} 254 | 255 | ## Add init containers to the pod. 256 | ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ 257 | ## e.g: 258 | ## initContainers: 259 | ## - name: your-image-name 260 | ## image: your-image 261 | ## imagePullPolicy: Always 262 | ## command: ['sh', '-c', 'copy themes and plugins from git and push to /bitnami/wordpress/wp-content. Should work with extraVolumeMounts and extraVolumes'] 263 | ## 264 | initContainers: {} 265 | 266 | ## Pod Labels 267 | ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ 268 | ## 269 | podLabels: {} 270 | 271 | ## Pod annotations 272 | ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ 273 | ## 274 | podAnnotations: {} 275 | 276 | ## Pod affinity preset 277 | ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity 278 | ## Allowed values: soft, hard 279 | ## 280 | podAffinityPreset: "" 281 | 282 | ## Pod anti-affinity preset 283 | ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity 284 | ## Allowed values: soft, hard 285 | ## 286 | podAntiAffinityPreset: soft 287 | 288 | ## Node affinity preset 289 | ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity 290 | ## Allowed values: soft, hard 291 | ## 292 | nodeAffinityPreset: 293 | ## Node affinity type 294 | ## Allowed values: soft, hard 295 | ## 296 | type: "" 297 | ## Node label key to match 298 | ## E.g. 299 | ## key: "kubernetes.io/e2e-az-name" 300 | ## 301 | key: "" 302 | ## Node label values to match 303 | ## E.g. 304 | ## values: 305 | ## - e2e-az1 306 | ## - e2e-az2 307 | ## 308 | values: [] 309 | 310 | ## Affinity for pod assignment 311 | ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity 312 | ## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set 313 | ## 314 | affinity: {} 315 | 316 | ## Node labels for pod assignment. Evaluated as a template. 317 | ## ref: https://kubernetes.io/docs/user-guide/node-selection/ 318 | ## 319 | nodeSelector: {} 320 | 321 | ## Tolerations for pod assignment. Evaluated as a template. 322 | ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ 323 | ## 324 | tolerations: {} 325 | 326 | ## WordPress containers' resource requests and limits 327 | ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ 328 | ## 329 | resources: 330 | limits: {} 331 | requests: 332 | memory: 512Mi 333 | cpu: 300m 334 | 335 | ## Configure Pods Security Context 336 | ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod 337 | ## 338 | podSecurityContext: 339 | enabled: true 340 | fsGroup: 1001 341 | 342 | ## Configure Container Security Context (only main container) 343 | ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container 344 | ## 345 | containerSecurityContext: 346 | enabled: true 347 | runAsUser: 1001 348 | 349 | ## WordPress containers' liveness and readiness probes. 350 | ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes 351 | ## 352 | livenessProbe: 353 | enabled: true 354 | httpGet: 355 | path: /wp-admin/install.php 356 | port: http 357 | scheme: HTTP 358 | ## If using an HTTPS-terminating load-balancer, the probes may need to behave 359 | ## like the balancer to prevent HTTP 302 responses. According to the Kubernetes 360 | ## docs, 302 should be considered "successful", but this issue on GitHub 361 | ## (https://github.com/kubernetes/kubernetes/issues/47893) shows that it isn't. 362 | ## 363 | ## httpHeaders: 364 | ## - name: X-Forwarded-Proto 365 | ## value: https 366 | ## 367 | httpHeaders: [] 368 | initialDelaySeconds: 120 369 | periodSeconds: 10 370 | timeoutSeconds: 5 371 | failureThreshold: 6 372 | successThreshold: 1 373 | readinessProbe: 374 | enabled: true 375 | httpGet: 376 | path: /wp-login.php 377 | port: http 378 | scheme: HTTP 379 | ## If using an HTTPS-terminating load-balancer, the probes may need to behave 380 | ## like the balancer to prevent HTTP 302 responses. According to the Kubernetes 381 | ## docs, 302 should be considered "successful", but this issue on GitHub 382 | ## (https://github.com/kubernetes/kubernetes/issues/47893) shows that it isn't. 383 | ## 384 | ## httpHeaders: 385 | ## - name: X-Forwarded-Proto 386 | ## value: https 387 | ## 388 | httpHeaders: [] 389 | initialDelaySeconds: 30 390 | periodSeconds: 10 391 | timeoutSeconds: 5 392 | failureThreshold: 6 393 | successThreshold: 1 394 | 395 | ## Custom liveness and readiness probes, it overrides the default one (evaluated as a template) 396 | ## 397 | customLivenessProbe: {} 398 | customReadinessProbe: {} 399 | 400 | ## Container ports 401 | ## 402 | containerPorts: 403 | http: 8080 404 | https: 8443 405 | 406 | ## WordPress Service properties 407 | ## 408 | service: 409 | ## WordPress Service type 410 | ## For minikube, set this to NodePort, elsewhere use LoadBalancer or ClusterIP 411 | ## 412 | type: LoadBalancer 413 | ## HTTP Port 414 | ## 415 | port: 80 416 | ## HTTPS Port 417 | ## 418 | httpsPort: 443 419 | ## HTTPS Target Port 420 | ## defaults to https unless overridden to the specified port. 421 | ## if you want the target port to be "http" or "80" you can specify that here. 422 | ## 423 | httpsTargetPort: https 424 | ## Node Ports to expose 425 | ## nodePorts: 426 | ## http: 427 | ## https: 428 | ## 429 | nodePorts: 430 | http: "" 431 | https: "" 432 | ## Service clusterIP 433 | ## 434 | # clusterIP: None 435 | ## loadBalancerIP for the SuiteCRM Service (optional, cloud specific) 436 | ## ref: http://kubernetes.io/docs/user-guide/services/#type-loadbalancer 437 | ## 438 | # loadBalancerIP: 439 | ## Load Balancer sources 440 | ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service 441 | ## e.g: 442 | ## loadBalancerSourceRanges: 443 | ## - 10.10.10.0/24 444 | ## 445 | loadBalancerSourceRanges: [] 446 | ## Enable client source IP preservation 447 | ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip 448 | ## 449 | externalTrafficPolicy: Cluster 450 | ## Provide any additional annotations which may be required (evaluated as a template). 451 | ## 452 | annotations: {} 453 | ## Extra ports to expose (normally used with the `sidecar` value) 454 | ## 455 | # extraPorts: 456 | 457 | ## Configure the ingress resource that allows you to access the 458 | ## WordPress installation. Set up the URL 459 | ## ref: http://kubernetes.io/docs/user-guide/ingress/ 460 | ## 461 | ingress: 462 | ## Set to true to enable ingress record generation 463 | ## 464 | enabled: false 465 | 466 | ## Set this to true in order to add the corresponding annotations for cert-manager 467 | ## 468 | certManager: false 469 | 470 | ## Ingress Path type 471 | ## 472 | pathType: ImplementationSpecific 473 | 474 | ## Override API Version (automatically detected if not set) 475 | ## 476 | apiVersion: 477 | 478 | ## When the ingress is enabled, a host pointing to this will be created 479 | ## 480 | hostname: wordpress.local 481 | 482 | ## The Path to WordPress. You may need to set this to '/*' in order to use this 483 | ## with ALB ingress controllers. 484 | ## 485 | path: / 486 | 487 | ## Ingress annotations done as key:value pairs 488 | ## For a full list of possible ingress annotations, please see 489 | ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md 490 | ## 491 | ## If certManager is set to true, annotation kubernetes.io/tls-acme: "true" will automatically be set 492 | ## 493 | annotations: {} 494 | 495 | ## Enable TLS configuration for the hostname defined at ingress.hostname parameter 496 | ## TLS certificates will be retrieved from a TLS secret with name: {{- printf "%s-tls" .Values.ingress.hostname }} 497 | ## You can use the ingress.secrets parameter to create this TLS secret or relay on cert-manager to create it 498 | ## 499 | tls: false 500 | 501 | ## The list of additional hostnames to be covered with this ingress record. 502 | ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array 503 | ## e.g: 504 | ## extraHosts: 505 | ## - name: wordpress.local 506 | ## path: / 507 | ## 508 | extraHosts: [] 509 | 510 | ## Any additional arbitrary paths that may need to be added to the ingress under the main host. 511 | ## For example: The ALB ingress controller requires a special rule for handling SSL redirection. 512 | ## extraPaths: 513 | ## - path: /* 514 | ## backend: 515 | ## serviceName: ssl-redirect 516 | ## servicePort: use-annotation 517 | ## 518 | extraPaths: [] 519 | 520 | ## The tls configuration for additional hostnames to be covered with this ingress record. 521 | ## see: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls 522 | ## e.g: 523 | ## extraTls: 524 | ## - hosts: 525 | ## - wordpress.local 526 | ## secretName: wordpress.local-tls 527 | ## 528 | extraTls: [] 529 | 530 | ## If you're providing your own certificates, please use this to add the certificates as secrets 531 | ## key and certificate are expected in PEM format 532 | ## name should line up with a secretName set further up 533 | ## 534 | ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates 535 | ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days 536 | ## It is also possible to create and manage the certificates outside of this helm chart 537 | ## Please see README.md for more information 538 | ## 539 | ## Example 540 | ## secrets: 541 | ## - name: wordpress.local-tls 542 | ## key: "" 543 | ## certificate: "" 544 | ## 545 | secrets: [] 546 | 547 | ## Enable persistence using Persistent Volume Claims 548 | ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ 549 | ## 550 | persistence: 551 | ## If true, use a Persistent Volume Claim, If false, use emptyDir 552 | ## 553 | enabled: true 554 | ## wordpress data Persistent Volume Storage Class 555 | ## If defined, storageClassName: 556 | ## If set to "-", storageClassName: "", which disables dynamic provisioning 557 | ## If undefined (the default) or set to null, no storageClassName spec is 558 | ## set, choosing the default provisioner. (gp2 on AWS, standard on 559 | ## GKE, AWS & OpenStack) 560 | ## 561 | # storageClass: "-" 562 | ## Persistent Volume Access Modes 563 | ## 564 | accessModes: 565 | - ReadWriteOnce 566 | ## DEPRECATED: use `persistence.accessModes` instead 567 | accessMode: ReadWriteOnce 568 | ## Persistent Volume size 569 | ## 570 | size: 10Gi 571 | ## Custom dataSource 572 | ## 573 | dataSource: {} 574 | ## Enable persistence using an existing PVC 575 | ## 576 | # existingClaim: 577 | 578 | ## Init containers parameters: 579 | ## volumePermissions: Change the owner and group of the persistent volume mount point to runAsUser:fsGroup values 580 | ## based on the podSecurityContext/containerSecurityContext parameters 581 | ## 582 | volumePermissions: 583 | enabled: false 584 | image: 585 | registry: docker.io 586 | repository: bitnami/bitnami-shell 587 | tag: "10" 588 | pullPolicy: Always 589 | ## Optionally specify an array of imagePullSecrets. 590 | ## Secrets must be manually created in the namespace. 591 | ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ 592 | ## e.g: 593 | ## pullSecrets: 594 | ## - myRegistryKeySecretName 595 | ## 596 | pullSecrets: [] 597 | ## Init container' resource requests and limits 598 | ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ 599 | ## 600 | resources: 601 | ## We usually recommend not to specify default resources and to leave this as a conscious 602 | ## choice for the user. This also increases chances charts run on environments with little 603 | ## resources, such as Minikube. If you do want to specify resources, uncomment the following 604 | ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. 605 | ## e.g: 606 | ## limits: 607 | ## cpu: 500m 608 | ## memory: 1Gi 609 | ## 610 | limits: {} 611 | requests: {} 612 | ## Init container Security Context 613 | ## Note: the chown of the data folder is done to containerSecurityContext.runAsUser 614 | ## and not the below volumePermissions.securityContext.runAsUser 615 | ## When runAsUser is set to special value "auto", init container will try to chwon the 616 | ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` 617 | ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). 618 | ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with 619 | ## podSecurityContext.enabled=false,containerSecurityContext.enabled=false 620 | ## 621 | securityContext: 622 | runAsUser: 0 623 | 624 | ## Wordpress Pod Disruption Budget configuration 625 | ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ 626 | ## 627 | pdb: 628 | create: false 629 | ## Min number of pods that must still be available after the eviction 630 | ## 631 | minAvailable: 1 632 | ## Max number of pods that can be unavailable after the eviction 633 | ## 634 | # maxUnavailable: 1 635 | 636 | ## Wordpress Autoscaling configuration 637 | ## 638 | autoscaling: 639 | enabled: false 640 | minReplicas: 1 641 | maxReplicas: 11 642 | # targetCPU: 50 643 | # targetMemory: 50 644 | 645 | ## Prometheus Exporter / Metrics 646 | ## 647 | metrics: 648 | enabled: false 649 | image: 650 | registry: docker.io 651 | repository: bitnami/apache-exporter 652 | tag: 0.8.0-debian-10-r332 653 | pullPolicy: IfNotPresent 654 | ## Optionally specify an array of imagePullSecrets. 655 | ## Secrets must be manually created in the namespace. 656 | ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ 657 | ## e.g: 658 | ## pullSecrets: 659 | ## - myRegistryKeySecretName 660 | ## 661 | pullSecrets: [] 662 | 663 | ## Prometheus expoter service parameters 664 | ## 665 | service: 666 | ## Metrics port 667 | ## 668 | port: 9117 669 | ## Annotations for the Prometheus exporter service 670 | ## 671 | annotations: 672 | prometheus.io/scrape: "true" 673 | prometheus.io/port: "{{ .Values.metrics.service.port }}" 674 | 675 | ## Metrics exporter containers' resource requests and limits 676 | ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ 677 | ## 678 | resources: 679 | limits: {} 680 | requests: {} 681 | 682 | ## Prometheus Service Monitor 683 | ## ref: https://github.com/coreos/prometheus-operator 684 | ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint 685 | ## 686 | serviceMonitor: 687 | ## If the operator is installed in your cluster, set to true to create a Service Monitor Entry 688 | ## 689 | enabled: false 690 | ## Specify the namespace in which the serviceMonitor resource will be created 691 | ## 692 | # namespace: "" 693 | ## Specify the interval at which metrics should be scraped 694 | ## 695 | interval: 30s 696 | ## Specify the timeout after which the scrape is ended 697 | ## 698 | # scrapeTimeout: 30s 699 | ## Specify Metric Relabellings to add to the scrape endpoint 700 | ## 701 | # relabellings: 702 | ## Specify honorLabels parameter to add the scrape endpoint 703 | ## 704 | honorLabels: false 705 | ## Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with 706 | ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec 707 | ## 708 | additionalLabels: {} 709 | 710 | ## 711 | ## MariaDB chart configuration 712 | ## ref: https://github.com/bitnami/charts/blob/master/bitnami/mariadb/values.yaml 713 | ## 714 | mariadb: 715 | ## Whether to deploy a mariadb server to satisfy the applications database requirements. To use an external database set this to false and configure the externalDatabase parameters 716 | ## 717 | enabled: true 718 | ## MariaDB architecture. Allowed values: standalone or replication 719 | ## 720 | architecture: standalone 721 | ## MariaDB Authentication parameters 722 | ## 723 | auth: 724 | ## MariaDB root password 725 | ## ref: https://github.com/bitnami/bitnami-docker-mariadb#setting-the-root-password-on-first-run 726 | ## 727 | rootPassword: "" 728 | ## MariaDB custom user and database 729 | ## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#creating-a-database-on-first-run 730 | ## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#creating-a-database-user-on-first-run 731 | ## 732 | database: bitnami_wordpress 733 | username: bn_wordpress 734 | password: "" 735 | primary: 736 | ## Enable persistence using Persistent Volume Claims 737 | ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ 738 | ## 739 | persistence: 740 | enabled: true 741 | ## mariadb data Persistent Volume Storage Class 742 | ## If defined, storageClassName: 743 | ## If set to "-", storageClassName: "", which disables dynamic provisioning 744 | ## If undefined (the default) or set to null, no storageClassName spec is 745 | ## set, choosing the default provisioner. (gp2 on AWS, standard on 746 | ## GKE, AWS & OpenStack) 747 | ## 748 | # storageClass: "-" 749 | accessModes: 750 | - ReadWriteOnce 751 | size: 8Gi 752 | 753 | ## 754 | ## External Database Configuration 755 | ## 756 | ## All of these values are only used when mariadb.enabled is set to false 757 | ## 758 | externalDatabase: 759 | ## Database host 760 | ## 761 | host: localhost 762 | ## non-root Username for Wordpress Database 763 | ## 764 | user: bn_wordpress 765 | ## Database password 766 | ## 767 | password: "" 768 | ## Database name 769 | ## 770 | database: bitnami_wordpress 771 | ## Database port number 772 | ## 773 | port: 3306 774 | ## Use existing secret (ignores previous password) 775 | ## must contain key `mariadb-password` 776 | ## NOTE: When it's set, the `externalDatabase.password` parameter is ignored 777 | ## 778 | # existingSecret: 779 | 780 | ## 781 | ## Memcached chart configuration 782 | ## ref: https://github.com/bitnami/charts/blob/master/bitnami/memcached/values.yaml 783 | ## 784 | memcached: 785 | ## Whether to deploy a memcached server for caching database queries 786 | ## 787 | enabled: false 788 | ## Service parameters 789 | ## 790 | service: 791 | ## Memcached port 792 | ## 793 | port: 11211 794 | -------------------------------------------------------------------------------- /Chapter18/01_serviceaccount/example-account-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: example-account 5 | namespace: default 6 | -------------------------------------------------------------------------------- /Chapter18/01_serviceaccount/pod-reader-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | namespace: default 5 | name: pod-reader 6 | rules: 7 | - apiGroups: [""] 8 | resources: ["pods"] 9 | verbs: ["get", "watch", "list"] 10 | -------------------------------------------------------------------------------- /Chapter18/01_serviceaccount/read-pods-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: read-pods 5 | namespace: default 6 | subjects: 7 | - kind: ServiceAccount 8 | name: example-account 9 | namespace: default 10 | roleRef: 11 | kind: Role 12 | name: pod-reader 13 | apiGroup: rbac.authorization.k8s.io 14 | -------------------------------------------------------------------------------- /Chapter18/02_rbac/pod-logger-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: pod-logger 5 | namespace: default 6 | -------------------------------------------------------------------------------- /Chapter18/02_rbac/pod-logger-static-pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-logger-static 5 | spec: 6 | serviceAccountName: pod-logger 7 | containers: 8 | - name: logger 9 | image: radial/busyboxplus:curl 10 | command: 11 | - /bin/sh 12 | - -c 13 | - | 14 | SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount 15 | TOKEN=$(cat ${SERVICEACCOUNT}/token) 16 | while true 17 | do 18 | echo "Querying Kubernetes API Server for Pods in default namespace..." 19 | curl --cacert $SERVICEACCOUNT/ca.crt --header "Authorization: Bearer $TOKEN" -X GET https://kubernetes/api/v1/namespaces/default/pods 20 | sleep 10 21 | done 22 | -------------------------------------------------------------------------------- /Chapter18/02_rbac/pod-reader-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | namespace: default 5 | name: pod-reader 6 | rules: 7 | - apiGroups: [""] 8 | resources: ["pods"] 9 | verbs: ["get", "watch", "list"] 10 | -------------------------------------------------------------------------------- /Chapter18/02_rbac/read-pods-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: read-pods 5 | namespace: default 6 | subjects: 7 | - kind: ServiceAccount 8 | name: pod-logger 9 | namespace: default 10 | roleRef: 11 | kind: Role 12 | name: pod-reader 13 | apiGroup: rbac.authorization.k8s.io 14 | -------------------------------------------------------------------------------- /Chapter18/03_aks-aad-rbac/aks-pod-writer.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "AKS Pods Writer", 3 | "Description": "Allows read-write management of Pods in cluster/namespace.", 4 | "Actions": [], 5 | "NotActions": [], 6 | "DataActions": [ 7 | "Microsoft.ContainerService/managedClusters/pods/read", 8 | "Microsoft.ContainerService/managedClusters/pods/write", 9 | "Microsoft.ContainerService/managedClusters/pods/delete" 10 | ], 11 | "NotDataActions": [], 12 | "assignableScopes": [ 13 | "/subscriptions/" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Chapter19/01_nodename/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 5 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | environment: test 16 | spec: 17 | nodeName: aks-nodepool1-77120516-vmss000000 18 | containers: 19 | - name: nginx 20 | image: nginx:1.17 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /Chapter19/02_nodeselector/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 5 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | environment: test 16 | spec: 17 | nodeSelector: 18 | node-type: superfast 19 | containers: 20 | - name: nginx 21 | image: nginx:1.17 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /Chapter19/03_affinity/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 5 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | environment: test 16 | spec: 17 | affinity: 18 | nodeAffinity: 19 | requiredDuringSchedulingIgnoredDuringExecution: 20 | nodeSelectorTerms: 21 | - matchExpressions: 22 | - key: node-type 23 | operator: NotIn 24 | values: 25 | - extremelyslow 26 | preferredDuringSchedulingIgnoredDuringExecution: 27 | - weight: 1 28 | preference: 29 | matchExpressions: 30 | - key: node-type 31 | operator: In 32 | values: 33 | - fast 34 | - superfast 35 | containers: 36 | - name: nginx 37 | image: nginx:1.17 38 | ports: 39 | - containerPort: 80 40 | -------------------------------------------------------------------------------- /Chapter19/04_taints/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 5 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | environment: test 16 | spec: 17 | tolerations: 18 | - key: machine-check-exception 19 | operator: Equal 20 | value: memory 21 | effect: NoExecute 22 | tolerationSeconds: 60 23 | containers: 24 | - name: nginx 25 | image: nginx:1.17 26 | ports: 27 | - containerPort: 80 28 | -------------------------------------------------------------------------------- /Chapter20/01_resource-requests-and-limits/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 5 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | environment: test 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | environment: test 16 | spec: 17 | containers: 18 | - name: nginx 19 | image: nginx:1.17 20 | ports: 21 | - containerPort: 80 22 | resources: 23 | limits: 24 | cpu: 200m 25 | memory: 60Mi 26 | requests: 27 | cpu: 100m 28 | memory: 50Mi 29 | -------------------------------------------------------------------------------- /Chapter20/02_vpa/hamster-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: hamster 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: hamster 9 | replicas: 5 10 | template: 11 | metadata: 12 | labels: 13 | app: hamster 14 | spec: 15 | containers: 16 | - name: hamster 17 | image: ubuntu:20.04 18 | resources: 19 | requests: 20 | cpu: 100m 21 | memory: 50Mi 22 | command: 23 | - /bin/sh 24 | - -c 25 | - while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done 26 | -------------------------------------------------------------------------------- /Chapter20/02_vpa/hamster-vpa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling.k8s.io/v1 2 | kind: VerticalPodAutoscaler 3 | metadata: 4 | name: hamster-vpa 5 | spec: 6 | targetRef: 7 | apiVersion: apps/v1 8 | kind: Deployment 9 | name: hamster 10 | updatePolicy: 11 | updateMode: Auto 12 | resourcePolicy: 13 | containerPolicies: 14 | - containerName: '*' 15 | minAllowed: 16 | cpu: 100m 17 | memory: 50Mi 18 | maxAllowed: 19 | cpu: 1 20 | memory: 500Mi 21 | controlledResources: 22 | - cpu 23 | - memory 24 | -------------------------------------------------------------------------------- /Chapter20/03_hpa/deployment-reader-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | namespace: default 5 | name: deployment-reader 6 | rules: 7 | - apiGroups: ["apps"] 8 | resources: ["deployments"] 9 | verbs: ["get", "watch", "list"] 10 | -------------------------------------------------------------------------------- /Chapter20/03_hpa/elastic-hamster-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: elastic-hamster 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: elastic-hamster 9 | replicas: 5 10 | template: 11 | metadata: 12 | labels: 13 | app: elastic-hamster 14 | spec: 15 | serviceAccountName: elastic-hamster 16 | containers: 17 | - name: hamster 18 | image: ubuntu:20.04 19 | resources: 20 | requests: 21 | cpu: 200m 22 | memory: 50Mi 23 | env: 24 | - name: TOTAL_HAMSTER_USAGE 25 | value: "1.0" 26 | command: 27 | - /bin/sh 28 | - -c 29 | - | 30 | # Install curl and jq 31 | apt-get update && apt-get install -y curl jq || exit 1 32 | 33 | SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount 34 | TOKEN=$(cat ${SERVICEACCOUNT}/token) 35 | 36 | while true 37 | # Calculate CPU usage by hamster. This will dynamically adjust to be 1.0 / num_replicas. So for initial 5 replicas, it will be 0.2 38 | HAMSTER_USAGE=$(curl -s --cacert $SERVICEACCOUNT/ca.crt --header "Authorization: Bearer $TOKEN" -X GET https://kubernetes/apis/apps/v1/namespaces/default/deployments/elastic-hamster | jq ${TOTAL_HAMSTER_USAGE}/'.spec.replicas') 39 | 40 | # Hamster sleeps for the rest of the time, with a small adjustment factor 41 | HAMSTER_SLEEP=$(jq -n 1.2-$HAMSTER_USAGE) 42 | 43 | echo "Hamster uses $HAMSTER_USAGE and sleeps $HAMSTER_SLEEP" 44 | do timeout ${HAMSTER_USAGE}s yes >/dev/null 45 | sleep ${HAMSTER_SLEEP}s 46 | done 47 | -------------------------------------------------------------------------------- /Chapter20/03_hpa/elastic-hamster-hpa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: elastic-hamster-hpa 5 | spec: 6 | minReplicas: 1 7 | maxReplicas: 10 8 | targetCPUUtilizationPercentage: 75 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: elastic-hamster 13 | -------------------------------------------------------------------------------- /Chapter20/03_hpa/elastic-hamster-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: elastic-hamster 5 | namespace: default 6 | -------------------------------------------------------------------------------- /Chapter20/03_hpa/read-deployments-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: read-deployments 5 | namespace: default 6 | subjects: 7 | - kind: ServiceAccount 8 | name: elastic-hamster 9 | namespace: default 10 | roleRef: 11 | kind: Role 12 | name: deployment-reader 13 | apiGroup: rbac.authorization.k8s.io 14 | -------------------------------------------------------------------------------- /Chapter20/04_clusterautoscaler/deployment-reader-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | namespace: default 5 | name: deployment-reader 6 | rules: 7 | - apiGroups: ["apps"] 8 | resources: ["deployments"] 9 | verbs: ["get", "watch", "list"] 10 | -------------------------------------------------------------------------------- /Chapter20/04_clusterautoscaler/elastic-hamster-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: elastic-hamster 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: elastic-hamster 9 | replicas: 7 10 | template: 11 | metadata: 12 | labels: 13 | app: elastic-hamster 14 | spec: 15 | serviceAccountName: elastic-hamster 16 | containers: 17 | - name: hamster 18 | image: ubuntu:20.04 19 | resources: 20 | requests: 21 | cpu: 500m 22 | memory: 50Mi 23 | env: 24 | - name: TOTAL_HAMSTER_USAGE 25 | value: "7.0" 26 | command: 27 | - /bin/sh 28 | - -c 29 | - | 30 | # Install curl and jq 31 | apt-get update && apt-get install -y curl jq || exit 1 32 | 33 | SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount 34 | TOKEN=$(cat ${SERVICEACCOUNT}/token) 35 | 36 | while true 37 | # Calculate CPU usage by hamster. This will dynamically adjust to be 1.0 / num_replicas. So for initial 5 replicas, it will be 0.2 38 | HAMSTER_USAGE=$(curl -s --cacert $SERVICEACCOUNT/ca.crt --header "Authorization: Bearer $TOKEN" -X GET https://kubernetes/apis/apps/v1/namespaces/default/deployments/elastic-hamster | jq ${TOTAL_HAMSTER_USAGE}/'.spec.replicas') 39 | 40 | # Hamster sleeps for the rest of the time, with a small adjustment factor 41 | HAMSTER_SLEEP=$(jq -n 1.2-$HAMSTER_USAGE) 42 | 43 | echo "Hamster uses $HAMSTER_USAGE and sleeps $HAMSTER_SLEEP" 44 | do timeout ${HAMSTER_USAGE}s yes >/dev/null 45 | sleep ${HAMSTER_SLEEP}s 46 | done 47 | -------------------------------------------------------------------------------- /Chapter20/04_clusterautoscaler/elastic-hamster-hpa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: elastic-hamster-hpa 5 | spec: 6 | minReplicas: 1 7 | maxReplicas: 25 8 | targetCPUUtilizationPercentage: 75 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: elastic-hamster 13 | -------------------------------------------------------------------------------- /Chapter20/04_clusterautoscaler/elastic-hamster-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: elastic-hamster 5 | namespace: default 6 | -------------------------------------------------------------------------------- /Chapter20/04_clusterautoscaler/read-deployments-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: read-deployments 5 | namespace: default 6 | subjects: 7 | - kind: ServiceAccount 8 | name: elastic-hamster 9 | namespace: default 10 | roleRef: 11 | kind: Role 12 | name: deployment-reader 13 | apiGroup: rbac.authorization.k8s.io 14 | -------------------------------------------------------------------------------- /Chapter21/01_services-recap/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment-example 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | environment: test 10 | template: 11 | metadata: 12 | labels: 13 | environment: test 14 | spec: 15 | containers: 16 | - name: nginx 17 | image: nginx:1.17 18 | ports: 19 | - containerPort: 80 20 | -------------------------------------------------------------------------------- /Chapter21/01_services-recap/nginx-service-clusterip.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-deployment-example-clusterip 5 | spec: 6 | selector: 7 | environment: test 8 | type: ClusterIP 9 | ports: 10 | - port: 8080 11 | protocol: TCP 12 | targetPort: 80 13 | -------------------------------------------------------------------------------- /Chapter21/01_services-recap/nginx-service-nodeport.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-deployment-example-nodeport 5 | spec: 6 | selector: 7 | environment: test 8 | type: NodePort 9 | ports: 10 | - port: 8080 11 | nodePort: 31001 12 | protocol: TCP 13 | targetPort: 80 14 | -------------------------------------------------------------------------------- /Chapter21/02_ingress/example-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: example-ingress 5 | annotations: 6 | nginx.ingress.kubernetes.io/rewrite-target: / 7 | spec: 8 | rules: 9 | - http: 10 | paths: 11 | - path: /service1 12 | pathType: Prefix 13 | backend: 14 | serviceName: example-service1 15 | servicePort: 80 16 | - path: /service2 17 | pathType: Prefix 18 | backend: 19 | serviceName: example-service2 20 | servicePort: 80 21 | -------------------------------------------------------------------------------- /Chapter21/02_ingress/example-services.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: example-service1 6 | spec: 7 | replicas: 3 8 | selector: 9 | matchLabels: 10 | app: example-service1 11 | environment: test 12 | template: 13 | metadata: 14 | labels: 15 | app: example-service1 16 | environment: test 17 | spec: 18 | containers: 19 | - name: nginx 20 | image: nginx:1.17 21 | ports: 22 | - containerPort: 80 23 | command: 24 | - /bin/sh 25 | - -c 26 | - | 27 | echo "Welcome to example-service1! You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html 28 | nginx -g "daemon off;" 29 | --- 30 | apiVersion: apps/v1 31 | kind: Deployment 32 | metadata: 33 | name: example-service2 34 | spec: 35 | replicas: 3 36 | selector: 37 | matchLabels: 38 | app: example-service2 39 | environment: test 40 | template: 41 | metadata: 42 | labels: 43 | app: example-service2 44 | environment: test 45 | spec: 46 | containers: 47 | - name: nginx 48 | image: nginx:1.17 49 | ports: 50 | - containerPort: 80 51 | command: 52 | - /bin/sh 53 | - -c 54 | - | 55 | echo "Welcome to example-service2! You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html 56 | nginx -g "daemon off;" 57 | --- 58 | apiVersion: v1 59 | kind: Service 60 | metadata: 61 | name: example-service1 62 | spec: 63 | selector: 64 | app: example-service1 65 | environment: test 66 | type: ClusterIP 67 | ports: 68 | - protocol: TCP 69 | port: 80 70 | --- 71 | apiVersion: v1 72 | kind: Service 73 | metadata: 74 | name: example-service2 75 | spec: 76 | selector: 77 | app: example-service2 78 | environment: test 79 | type: ClusterIP 80 | ports: 81 | - protocol: TCP 82 | port: 80 83 | -------------------------------------------------------------------------------- /Chapter21/02_ingress/nginx-ingresscontroller-cloud.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: ingress-nginx 6 | labels: 7 | app.kubernetes.io/name: ingress-nginx 8 | app.kubernetes.io/instance: ingress-nginx 9 | 10 | --- 11 | # Source: ingress-nginx/templates/controller-serviceaccount.yaml 12 | apiVersion: v1 13 | kind: ServiceAccount 14 | metadata: 15 | labels: 16 | helm.sh/chart: ingress-nginx-3.23.0 17 | app.kubernetes.io/name: ingress-nginx 18 | app.kubernetes.io/instance: ingress-nginx 19 | app.kubernetes.io/version: 0.44.0 20 | app.kubernetes.io/managed-by: Helm 21 | app.kubernetes.io/component: controller 22 | name: ingress-nginx 23 | namespace: ingress-nginx 24 | --- 25 | # Source: ingress-nginx/templates/controller-configmap.yaml 26 | apiVersion: v1 27 | kind: ConfigMap 28 | metadata: 29 | labels: 30 | helm.sh/chart: ingress-nginx-3.23.0 31 | app.kubernetes.io/name: ingress-nginx 32 | app.kubernetes.io/instance: ingress-nginx 33 | app.kubernetes.io/version: 0.44.0 34 | app.kubernetes.io/managed-by: Helm 35 | app.kubernetes.io/component: controller 36 | name: ingress-nginx-controller 37 | namespace: ingress-nginx 38 | data: 39 | --- 40 | # Source: ingress-nginx/templates/clusterrole.yaml 41 | apiVersion: rbac.authorization.k8s.io/v1 42 | kind: ClusterRole 43 | metadata: 44 | labels: 45 | helm.sh/chart: ingress-nginx-3.23.0 46 | app.kubernetes.io/name: ingress-nginx 47 | app.kubernetes.io/instance: ingress-nginx 48 | app.kubernetes.io/version: 0.44.0 49 | app.kubernetes.io/managed-by: Helm 50 | name: ingress-nginx 51 | rules: 52 | - apiGroups: 53 | - '' 54 | resources: 55 | - configmaps 56 | - endpoints 57 | - nodes 58 | - pods 59 | - secrets 60 | verbs: 61 | - list 62 | - watch 63 | - apiGroups: 64 | - '' 65 | resources: 66 | - nodes 67 | verbs: 68 | - get 69 | - apiGroups: 70 | - '' 71 | resources: 72 | - services 73 | verbs: 74 | - get 75 | - list 76 | - watch 77 | - apiGroups: 78 | - extensions 79 | - networking.k8s.io # k8s 1.14+ 80 | resources: 81 | - ingresses 82 | verbs: 83 | - get 84 | - list 85 | - watch 86 | - apiGroups: 87 | - '' 88 | resources: 89 | - events 90 | verbs: 91 | - create 92 | - patch 93 | - apiGroups: 94 | - extensions 95 | - networking.k8s.io # k8s 1.14+ 96 | resources: 97 | - ingresses/status 98 | verbs: 99 | - update 100 | - apiGroups: 101 | - networking.k8s.io # k8s 1.14+ 102 | resources: 103 | - ingressclasses 104 | verbs: 105 | - get 106 | - list 107 | - watch 108 | --- 109 | # Source: ingress-nginx/templates/clusterrolebinding.yaml 110 | apiVersion: rbac.authorization.k8s.io/v1 111 | kind: ClusterRoleBinding 112 | metadata: 113 | labels: 114 | helm.sh/chart: ingress-nginx-3.23.0 115 | app.kubernetes.io/name: ingress-nginx 116 | app.kubernetes.io/instance: ingress-nginx 117 | app.kubernetes.io/version: 0.44.0 118 | app.kubernetes.io/managed-by: Helm 119 | name: ingress-nginx 120 | roleRef: 121 | apiGroup: rbac.authorization.k8s.io 122 | kind: ClusterRole 123 | name: ingress-nginx 124 | subjects: 125 | - kind: ServiceAccount 126 | name: ingress-nginx 127 | namespace: ingress-nginx 128 | --- 129 | # Source: ingress-nginx/templates/controller-role.yaml 130 | apiVersion: rbac.authorization.k8s.io/v1 131 | kind: Role 132 | metadata: 133 | labels: 134 | helm.sh/chart: ingress-nginx-3.23.0 135 | app.kubernetes.io/name: ingress-nginx 136 | app.kubernetes.io/instance: ingress-nginx 137 | app.kubernetes.io/version: 0.44.0 138 | app.kubernetes.io/managed-by: Helm 139 | app.kubernetes.io/component: controller 140 | name: ingress-nginx 141 | namespace: ingress-nginx 142 | rules: 143 | - apiGroups: 144 | - '' 145 | resources: 146 | - namespaces 147 | verbs: 148 | - get 149 | - apiGroups: 150 | - '' 151 | resources: 152 | - configmaps 153 | - pods 154 | - secrets 155 | - endpoints 156 | verbs: 157 | - get 158 | - list 159 | - watch 160 | - apiGroups: 161 | - '' 162 | resources: 163 | - services 164 | verbs: 165 | - get 166 | - list 167 | - watch 168 | - apiGroups: 169 | - extensions 170 | - networking.k8s.io # k8s 1.14+ 171 | resources: 172 | - ingresses 173 | verbs: 174 | - get 175 | - list 176 | - watch 177 | - apiGroups: 178 | - extensions 179 | - networking.k8s.io # k8s 1.14+ 180 | resources: 181 | - ingresses/status 182 | verbs: 183 | - update 184 | - apiGroups: 185 | - networking.k8s.io # k8s 1.14+ 186 | resources: 187 | - ingressclasses 188 | verbs: 189 | - get 190 | - list 191 | - watch 192 | - apiGroups: 193 | - '' 194 | resources: 195 | - configmaps 196 | resourceNames: 197 | - ingress-controller-leader-nginx 198 | verbs: 199 | - get 200 | - update 201 | - apiGroups: 202 | - '' 203 | resources: 204 | - configmaps 205 | verbs: 206 | - create 207 | - apiGroups: 208 | - '' 209 | resources: 210 | - events 211 | verbs: 212 | - create 213 | - patch 214 | --- 215 | # Source: ingress-nginx/templates/controller-rolebinding.yaml 216 | apiVersion: rbac.authorization.k8s.io/v1 217 | kind: RoleBinding 218 | metadata: 219 | labels: 220 | helm.sh/chart: ingress-nginx-3.23.0 221 | app.kubernetes.io/name: ingress-nginx 222 | app.kubernetes.io/instance: ingress-nginx 223 | app.kubernetes.io/version: 0.44.0 224 | app.kubernetes.io/managed-by: Helm 225 | app.kubernetes.io/component: controller 226 | name: ingress-nginx 227 | namespace: ingress-nginx 228 | roleRef: 229 | apiGroup: rbac.authorization.k8s.io 230 | kind: Role 231 | name: ingress-nginx 232 | subjects: 233 | - kind: ServiceAccount 234 | name: ingress-nginx 235 | namespace: ingress-nginx 236 | --- 237 | # Source: ingress-nginx/templates/controller-service-webhook.yaml 238 | apiVersion: v1 239 | kind: Service 240 | metadata: 241 | labels: 242 | helm.sh/chart: ingress-nginx-3.23.0 243 | app.kubernetes.io/name: ingress-nginx 244 | app.kubernetes.io/instance: ingress-nginx 245 | app.kubernetes.io/version: 0.44.0 246 | app.kubernetes.io/managed-by: Helm 247 | app.kubernetes.io/component: controller 248 | name: ingress-nginx-controller-admission 249 | namespace: ingress-nginx 250 | spec: 251 | type: ClusterIP 252 | ports: 253 | - name: https-webhook 254 | port: 443 255 | targetPort: webhook 256 | selector: 257 | app.kubernetes.io/name: ingress-nginx 258 | app.kubernetes.io/instance: ingress-nginx 259 | app.kubernetes.io/component: controller 260 | --- 261 | # Source: ingress-nginx/templates/controller-service.yaml 262 | apiVersion: v1 263 | kind: Service 264 | metadata: 265 | annotations: 266 | labels: 267 | helm.sh/chart: ingress-nginx-3.23.0 268 | app.kubernetes.io/name: ingress-nginx 269 | app.kubernetes.io/instance: ingress-nginx 270 | app.kubernetes.io/version: 0.44.0 271 | app.kubernetes.io/managed-by: Helm 272 | app.kubernetes.io/component: controller 273 | name: ingress-nginx-controller 274 | namespace: ingress-nginx 275 | spec: 276 | type: LoadBalancer 277 | externalTrafficPolicy: Local 278 | ports: 279 | - name: http 280 | port: 80 281 | protocol: TCP 282 | targetPort: http 283 | - name: https 284 | port: 443 285 | protocol: TCP 286 | targetPort: https 287 | selector: 288 | app.kubernetes.io/name: ingress-nginx 289 | app.kubernetes.io/instance: ingress-nginx 290 | app.kubernetes.io/component: controller 291 | --- 292 | # Source: ingress-nginx/templates/controller-deployment.yaml 293 | apiVersion: apps/v1 294 | kind: Deployment 295 | metadata: 296 | labels: 297 | helm.sh/chart: ingress-nginx-3.23.0 298 | app.kubernetes.io/name: ingress-nginx 299 | app.kubernetes.io/instance: ingress-nginx 300 | app.kubernetes.io/version: 0.44.0 301 | app.kubernetes.io/managed-by: Helm 302 | app.kubernetes.io/component: controller 303 | name: ingress-nginx-controller 304 | namespace: ingress-nginx 305 | spec: 306 | selector: 307 | matchLabels: 308 | app.kubernetes.io/name: ingress-nginx 309 | app.kubernetes.io/instance: ingress-nginx 310 | app.kubernetes.io/component: controller 311 | revisionHistoryLimit: 10 312 | minReadySeconds: 0 313 | template: 314 | metadata: 315 | labels: 316 | app.kubernetes.io/name: ingress-nginx 317 | app.kubernetes.io/instance: ingress-nginx 318 | app.kubernetes.io/component: controller 319 | spec: 320 | dnsPolicy: ClusterFirst 321 | containers: 322 | - name: controller 323 | image: k8s.gcr.io/ingress-nginx/controller:v0.44.0@sha256:3dd0fac48073beaca2d67a78c746c7593f9c575168a17139a9955a82c63c4b9a 324 | imagePullPolicy: IfNotPresent 325 | lifecycle: 326 | preStop: 327 | exec: 328 | command: 329 | - /wait-shutdown 330 | args: 331 | - /nginx-ingress-controller 332 | - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller 333 | - --election-id=ingress-controller-leader 334 | - --ingress-class=nginx 335 | - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller 336 | - --validating-webhook=:8443 337 | - --validating-webhook-certificate=/usr/local/certificates/cert 338 | - --validating-webhook-key=/usr/local/certificates/key 339 | securityContext: 340 | capabilities: 341 | drop: 342 | - ALL 343 | add: 344 | - NET_BIND_SERVICE 345 | runAsUser: 101 346 | allowPrivilegeEscalation: true 347 | env: 348 | - name: POD_NAME 349 | valueFrom: 350 | fieldRef: 351 | fieldPath: metadata.name 352 | - name: POD_NAMESPACE 353 | valueFrom: 354 | fieldRef: 355 | fieldPath: metadata.namespace 356 | - name: LD_PRELOAD 357 | value: /usr/local/lib/libmimalloc.so 358 | livenessProbe: 359 | httpGet: 360 | path: /healthz 361 | port: 10254 362 | scheme: HTTP 363 | initialDelaySeconds: 10 364 | periodSeconds: 10 365 | timeoutSeconds: 1 366 | successThreshold: 1 367 | failureThreshold: 5 368 | readinessProbe: 369 | httpGet: 370 | path: /healthz 371 | port: 10254 372 | scheme: HTTP 373 | initialDelaySeconds: 10 374 | periodSeconds: 10 375 | timeoutSeconds: 1 376 | successThreshold: 1 377 | failureThreshold: 3 378 | ports: 379 | - name: http 380 | containerPort: 80 381 | protocol: TCP 382 | - name: https 383 | containerPort: 443 384 | protocol: TCP 385 | - name: webhook 386 | containerPort: 8443 387 | protocol: TCP 388 | volumeMounts: 389 | - name: webhook-cert 390 | mountPath: /usr/local/certificates/ 391 | readOnly: true 392 | resources: 393 | requests: 394 | cpu: 100m 395 | memory: 90Mi 396 | nodeSelector: 397 | kubernetes.io/os: linux 398 | serviceAccountName: ingress-nginx 399 | terminationGracePeriodSeconds: 300 400 | volumes: 401 | - name: webhook-cert 402 | secret: 403 | secretName: ingress-nginx-admission 404 | --- 405 | # Source: ingress-nginx/templates/admission-webhooks/validating-webhook.yaml 406 | # before changing this value, check the required kubernetes version 407 | # https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites 408 | apiVersion: admissionregistration.k8s.io/v1 409 | kind: ValidatingWebhookConfiguration 410 | metadata: 411 | labels: 412 | helm.sh/chart: ingress-nginx-3.23.0 413 | app.kubernetes.io/name: ingress-nginx 414 | app.kubernetes.io/instance: ingress-nginx 415 | app.kubernetes.io/version: 0.44.0 416 | app.kubernetes.io/managed-by: Helm 417 | app.kubernetes.io/component: admission-webhook 418 | name: ingress-nginx-admission 419 | webhooks: 420 | - name: validate.nginx.ingress.kubernetes.io 421 | matchPolicy: Equivalent 422 | rules: 423 | - apiGroups: 424 | - networking.k8s.io 425 | apiVersions: 426 | - v1beta1 427 | operations: 428 | - CREATE 429 | - UPDATE 430 | resources: 431 | - ingresses 432 | failurePolicy: Fail 433 | sideEffects: None 434 | admissionReviewVersions: 435 | - v1 436 | - v1beta1 437 | clientConfig: 438 | service: 439 | namespace: ingress-nginx 440 | name: ingress-nginx-controller-admission 441 | path: /networking/v1beta1/ingresses 442 | --- 443 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml 444 | apiVersion: v1 445 | kind: ServiceAccount 446 | metadata: 447 | name: ingress-nginx-admission 448 | annotations: 449 | helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade 450 | helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded 451 | labels: 452 | helm.sh/chart: ingress-nginx-3.23.0 453 | app.kubernetes.io/name: ingress-nginx 454 | app.kubernetes.io/instance: ingress-nginx 455 | app.kubernetes.io/version: 0.44.0 456 | app.kubernetes.io/managed-by: Helm 457 | app.kubernetes.io/component: admission-webhook 458 | namespace: ingress-nginx 459 | --- 460 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml 461 | apiVersion: rbac.authorization.k8s.io/v1 462 | kind: ClusterRole 463 | metadata: 464 | name: ingress-nginx-admission 465 | annotations: 466 | helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade 467 | helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded 468 | labels: 469 | helm.sh/chart: ingress-nginx-3.23.0 470 | app.kubernetes.io/name: ingress-nginx 471 | app.kubernetes.io/instance: ingress-nginx 472 | app.kubernetes.io/version: 0.44.0 473 | app.kubernetes.io/managed-by: Helm 474 | app.kubernetes.io/component: admission-webhook 475 | rules: 476 | - apiGroups: 477 | - admissionregistration.k8s.io 478 | resources: 479 | - validatingwebhookconfigurations 480 | verbs: 481 | - get 482 | - update 483 | --- 484 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml 485 | apiVersion: rbac.authorization.k8s.io/v1 486 | kind: ClusterRoleBinding 487 | metadata: 488 | name: ingress-nginx-admission 489 | annotations: 490 | helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade 491 | helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded 492 | labels: 493 | helm.sh/chart: ingress-nginx-3.23.0 494 | app.kubernetes.io/name: ingress-nginx 495 | app.kubernetes.io/instance: ingress-nginx 496 | app.kubernetes.io/version: 0.44.0 497 | app.kubernetes.io/managed-by: Helm 498 | app.kubernetes.io/component: admission-webhook 499 | roleRef: 500 | apiGroup: rbac.authorization.k8s.io 501 | kind: ClusterRole 502 | name: ingress-nginx-admission 503 | subjects: 504 | - kind: ServiceAccount 505 | name: ingress-nginx-admission 506 | namespace: ingress-nginx 507 | --- 508 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/role.yaml 509 | apiVersion: rbac.authorization.k8s.io/v1 510 | kind: Role 511 | metadata: 512 | name: ingress-nginx-admission 513 | annotations: 514 | helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade 515 | helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded 516 | labels: 517 | helm.sh/chart: ingress-nginx-3.23.0 518 | app.kubernetes.io/name: ingress-nginx 519 | app.kubernetes.io/instance: ingress-nginx 520 | app.kubernetes.io/version: 0.44.0 521 | app.kubernetes.io/managed-by: Helm 522 | app.kubernetes.io/component: admission-webhook 523 | namespace: ingress-nginx 524 | rules: 525 | - apiGroups: 526 | - '' 527 | resources: 528 | - secrets 529 | verbs: 530 | - get 531 | - create 532 | --- 533 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml 534 | apiVersion: rbac.authorization.k8s.io/v1 535 | kind: RoleBinding 536 | metadata: 537 | name: ingress-nginx-admission 538 | annotations: 539 | helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade 540 | helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded 541 | labels: 542 | helm.sh/chart: ingress-nginx-3.23.0 543 | app.kubernetes.io/name: ingress-nginx 544 | app.kubernetes.io/instance: ingress-nginx 545 | app.kubernetes.io/version: 0.44.0 546 | app.kubernetes.io/managed-by: Helm 547 | app.kubernetes.io/component: admission-webhook 548 | namespace: ingress-nginx 549 | roleRef: 550 | apiGroup: rbac.authorization.k8s.io 551 | kind: Role 552 | name: ingress-nginx-admission 553 | subjects: 554 | - kind: ServiceAccount 555 | name: ingress-nginx-admission 556 | namespace: ingress-nginx 557 | --- 558 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml 559 | apiVersion: batch/v1 560 | kind: Job 561 | metadata: 562 | name: ingress-nginx-admission-create 563 | annotations: 564 | helm.sh/hook: pre-install,pre-upgrade 565 | helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded 566 | labels: 567 | helm.sh/chart: ingress-nginx-3.23.0 568 | app.kubernetes.io/name: ingress-nginx 569 | app.kubernetes.io/instance: ingress-nginx 570 | app.kubernetes.io/version: 0.44.0 571 | app.kubernetes.io/managed-by: Helm 572 | app.kubernetes.io/component: admission-webhook 573 | namespace: ingress-nginx 574 | spec: 575 | template: 576 | metadata: 577 | name: ingress-nginx-admission-create 578 | labels: 579 | helm.sh/chart: ingress-nginx-3.23.0 580 | app.kubernetes.io/name: ingress-nginx 581 | app.kubernetes.io/instance: ingress-nginx 582 | app.kubernetes.io/version: 0.44.0 583 | app.kubernetes.io/managed-by: Helm 584 | app.kubernetes.io/component: admission-webhook 585 | spec: 586 | containers: 587 | - name: create 588 | image: docker.io/jettech/kube-webhook-certgen:v1.5.1 589 | imagePullPolicy: IfNotPresent 590 | args: 591 | - create 592 | - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc 593 | - --namespace=$(POD_NAMESPACE) 594 | - --secret-name=ingress-nginx-admission 595 | env: 596 | - name: POD_NAMESPACE 597 | valueFrom: 598 | fieldRef: 599 | fieldPath: metadata.namespace 600 | restartPolicy: OnFailure 601 | serviceAccountName: ingress-nginx-admission 602 | securityContext: 603 | runAsNonRoot: true 604 | runAsUser: 2000 605 | --- 606 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml 607 | apiVersion: batch/v1 608 | kind: Job 609 | metadata: 610 | name: ingress-nginx-admission-patch 611 | annotations: 612 | helm.sh/hook: post-install,post-upgrade 613 | helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded 614 | labels: 615 | helm.sh/chart: ingress-nginx-3.23.0 616 | app.kubernetes.io/name: ingress-nginx 617 | app.kubernetes.io/instance: ingress-nginx 618 | app.kubernetes.io/version: 0.44.0 619 | app.kubernetes.io/managed-by: Helm 620 | app.kubernetes.io/component: admission-webhook 621 | namespace: ingress-nginx 622 | spec: 623 | template: 624 | metadata: 625 | name: ingress-nginx-admission-patch 626 | labels: 627 | helm.sh/chart: ingress-nginx-3.23.0 628 | app.kubernetes.io/name: ingress-nginx 629 | app.kubernetes.io/instance: ingress-nginx 630 | app.kubernetes.io/version: 0.44.0 631 | app.kubernetes.io/managed-by: Helm 632 | app.kubernetes.io/component: admission-webhook 633 | spec: 634 | containers: 635 | - name: patch 636 | image: docker.io/jettech/kube-webhook-certgen:v1.5.1 637 | imagePullPolicy: IfNotPresent 638 | args: 639 | - patch 640 | - --webhook-name=ingress-nginx-admission 641 | - --namespace=$(POD_NAMESPACE) 642 | - --patch-mutating=false 643 | - --secret-name=ingress-nginx-admission 644 | - --patch-failure-policy=Fail 645 | env: 646 | - name: POD_NAMESPACE 647 | valueFrom: 648 | fieldRef: 649 | fieldPath: metadata.namespace 650 | restartPolicy: OnFailure 651 | serviceAccountName: ingress-nginx-admission 652 | securityContext: 653 | runAsNonRoot: true 654 | runAsUser: 2000 655 | -------------------------------------------------------------------------------- /Chapter21/03_aks-agic/example-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: example-ingress 5 | annotations: 6 | kubernetes.io/ingress.class: azure/application-gateway 7 | appgw.ingress.kubernetes.io/backend-path-prefix: "/" 8 | spec: 9 | rules: 10 | - http: 11 | paths: 12 | - path: /service1 13 | backend: 14 | serviceName: example-service1 15 | servicePort: 80 16 | - path: /service2 17 | backend: 18 | serviceName: example-service2 19 | servicePort: 80 20 | -------------------------------------------------------------------------------- /Chapter21/03_aks-agic/example-services.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: example-service1 6 | spec: 7 | replicas: 3 8 | selector: 9 | matchLabels: 10 | app: example-service1 11 | environment: test 12 | template: 13 | metadata: 14 | labels: 15 | app: example-service1 16 | environment: test 17 | spec: 18 | containers: 19 | - name: nginx 20 | image: nginx:1.17 21 | ports: 22 | - containerPort: 80 23 | command: 24 | - /bin/sh 25 | - -c 26 | - | 27 | echo "Welcome to example-service1! You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html 28 | nginx -g "daemon off;" 29 | --- 30 | apiVersion: apps/v1 31 | kind: Deployment 32 | metadata: 33 | name: example-service2 34 | spec: 35 | replicas: 3 36 | selector: 37 | matchLabels: 38 | app: example-service2 39 | environment: test 40 | template: 41 | metadata: 42 | labels: 43 | app: example-service2 44 | environment: test 45 | spec: 46 | containers: 47 | - name: nginx 48 | image: nginx:1.17 49 | ports: 50 | - containerPort: 80 51 | command: 52 | - /bin/sh 53 | - -c 54 | - | 55 | echo "Welcome to example-service2! You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html 56 | nginx -g "daemon off;" 57 | --- 58 | apiVersion: v1 59 | kind: Service 60 | metadata: 61 | name: example-service1 62 | spec: 63 | selector: 64 | app: example-service1 65 | environment: test 66 | type: ClusterIP 67 | ports: 68 | - protocol: TCP 69 | port: 80 70 | --- 71 | apiVersion: v1 72 | kind: Service 73 | metadata: 74 | name: example-service2 75 | spec: 76 | selector: 77 | app: example-service2 78 | environment: test 79 | type: ClusterIP 80 | ports: 81 | - protocol: TCP 82 | port: 80 83 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # The Kubernetes Bible 5 | 6 | The Kubernetes Bible 7 | 8 | This is the code repository for [The Kubernetes Bible](https://www.packtpub.com/product/the-kubernetes-bible/9781838827694?utm_source=github&utm_medium=repository&utm_campaign=9781838827694), published by Packt. 9 | 10 | **The definitive guide to deploying and managing Kubernetes across major cloud platforms** 11 | 12 | ## What is this book about? 13 | With its broad adoption across various industries, Kubernetes is helping engineers with the orchestration and automation of container deployments on a large scale, making it the leading container orchestration system and the most popular choice for running containerized applications. 14 | 15 | This book covers the following exciting features: 16 | * Manage containerized applications with Kubernetes 17 | * Understand Kubernetes architecture and the responsibilities of each component 18 | * Set up Kubernetes on Amazon Elastic Kubernetes Service, Google Kubernetes Engine, and Microsoft Azure Kubernetes Service 19 | * Deploy cloud applications such as Prometheus and Elasticsearch using Helm charts 20 | * Discover advanced techniques for Pod scheduling and auto-scaling the cluster 21 | * Understand possible approaches to traffic routing in Kubernetes 22 | 23 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1838827692) today! 24 | 25 | https://www.packtpub.com/ 27 | 28 | ## Instructions and Navigations 29 | All of the code is organized into folders. For example, Chapter02. 30 | 31 | The code will look like the following: 32 | ``` 33 | apiVersion: v1 34 | kind: Pod 35 | metadata: 36 | name: nginx-Pod 37 | ``` 38 | 39 | **Following is what you need for this book:** 40 | This book is for software developers and DevOps engineers looking to understand how to work with Kubernetes for orchestrating containerized applications and services in the cloud. Prior experience with designing software running in operating system containers, as well as a general background in DevOps best practices, will be helpful. Basic knowledge of Kubernetes, Docker, and leading cloud service providers assist with grasping the concepts covered easily. 41 | 42 | With the following software and hardware list you can run all code files present in the book (Chapter 1-21). 43 | ### Software and Hardware List 44 | | Chapter | Software required | OS required | 45 | | -------- | ------------------------------------ | ----------------------------------- | 46 | | 1-21 | Kubernetes >= 1.17 | Windows, Mac OS X, and Linux (Any) | 47 | | 1-21 | Kubectl >=1.17 | Windows, Mac OS X, and Linux (Any) | 48 | 49 | We also provide a PDF file that has color images of the screenshots/diagrams used in this book. [Click here to download it](https://static.packt-cdn.com/downloads/9781838827694_ColorImages.pdf). 50 | 51 | ## Errata 52 | * Page 109: **kubectl run nginx-Pod --image nginx --label " tier=frontend"** _should be_ **kubectl run nginx-pod --image nginx --labels " tier-frontend"** 53 | 54 | ### Related products 55 | * Operational challenges with Kubernetes [[Packt]](https://www.packtpub.com/product/kubernetes-in-production-best-practices/9781800202450?utm_source=github&utm_medium=repository&utm_campaign=9781800202450) [[Amazon]](https://www.amazon.com/dp/1800202458) 56 | 57 | * Cloud Native with Kubernetes [[Packt]](https://www.packtpub.com/product/cloud-native-with-kubernetes/9781838823078?utm_source=github&utm_medium=repository&utm_campaign=9781838823078) [[Amazon]](https://www.amazon.com/dp/1838823077) 58 | 59 | ## Get to Know the Author 60 | **Nassim Kabbani** 61 | is an experienced software engineer with deep expertise in Kubernetes and the Amazon Web Services cloud provider. He has an extensive background both in software development and operations teams, implementing all the spectrum of a DevOps lifecycle chain, from application code to pipelines and monitoring in various industries such as e-commerce, media, and financial services. 62 | He implemented numerous cloud-native architectures and containerized applications on Docker and AWS and holds both Kubernetes CKA and CKAD certification 63 | 64 | **Piotr Tylenda** 65 | is an experienced DevOps and software engineer with a passion for Kubernetes and Azure technologies. In his projects, he has focused on the adoption of microservices architecture for monolithic applications, developing big data pipelines for e-commerce, and architecting solutions for scalable log and telemetry analytics for hardware. His most notable contribution to Kubernetes' open source ecosystem is the development of Ansible automation for provisioning and deploying hybrid Windows/Linux Kubernetes clusters. Currently, he works at Microsoft Development Center Copenhagen in Denmark in a team developing a Microsoft Dynamics 365 Business Central SaaS offering. 66 | 67 | **Russ McKendrick** 68 | is an experienced system administrator who has been working in IT and related industries for over 25 years. During his career, he has had varied responsibilities, from looking after an entire IT infrastructure to providing first-line, second-line, and senior support in both client-facing and internal teams for large organizations. 69 | Russ supports open source systems and tools on public and private clouds at N4Stack, a Node4 company, where he is the practice manager (SRE and DevOps). In his spare time, he has written several books including Mastering Docker, Learn Ansible and Kubernetes for Serverless Applications, all published by Packt Publishing. 70 | 71 | ## Other books by the authors 72 | * [Hands-On Kubernetes on Windows](https://www.packtpub.com/cloud-networking/hands-on-kubernetes-on-windows?utm_source=github&utm_medium=repository&utm_campaign=9781838821562) 73 | 74 | * [Learn Ansible](https://www.packtpub.com/virtualization-and-cloud/learn-ansible?utm_source=github&utm_medium=repository&utm_campaign=9781788998758) 75 | ### Download a free PDF 76 | 77 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
78 |

https://packt.link/free-ebook/9781838827694

79 | --------------------------------------------------------------------------------