diff --git a/README.md b/README.md index f029ad20..7e282041 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Docker Image Version (latest by date)](https://img.shields.io/docker/v/paulbouwer/hello-kubernetes)](https://hub.docker.com/repository/docker/paulbouwer/hello-kubernetes) [![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/paulbouwer/hello-kubernetes)](https://hub.docker.com/repository/docker/paulbouwer/hello-kubernetes) [![Docker Pulls](https://img.shields.io/docker/pulls/paulbouwer/hello-kubernetes)](https://hub.docker.com/repository/docker/paulbouwer/hello-kubernetes) -This container image can be deployed on a Kubernetes cluster. When accessed via a web browser on port `8080`, it will display: +This container image can be deployed on a Kubernetes cluster. It runs a static web site, that displays the following: - a default **Hello world!** message - the pod name @@ -10,167 +10,50 @@ This container image can be deployed on a Kubernetes cluster. When accessed via ![Hello world! from the hello-kubernetes image](hello-kubernetes.png) -The default "Hello world!" message displayed can be overridden using the `MESSAGE` environment variable. The default port of 8080 can be overriden using the `PORT` environment variable. - ## Deploy -### Standard Configuration - -Deploy to your Kubernetes cluster using the hello-kubernetes.yaml, which contains definitions for the service and deployment objects: - -```yaml -# hello-kubernetes.yaml -apiVersion: v1 -kind: Service -metadata: - name: hello-kubernetes -spec: - type: LoadBalancer - ports: - - port: 80 - targetPort: 8080 - selector: - app: hello-kubernetes ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: hello-kubernetes -spec: - replicas: 3 - selector: - matchLabels: - app: hello-kubernetes - template: - metadata: - labels: - app: hello-kubernetes - spec: - containers: - - name: hello-kubernetes - image: paulbouwer/hello-kubernetes:1.9 - ports: - - containerPort: 8080 -``` +You can deploy `hello-kubernetes` to your Kubernetes cluster using [Helm 3](https://helm.sh/docs/intro/install/). You can find all the `hello-kubernetes` Helm chart installation and configuration options in the [Deploy using Helm](docs/deploy-using-helm.md) guide. + +Ensure that you are in the chart directory in the repo, since you are referencing a local helm chart. ```bash -$ kubectl apply -f yaml/hello-kubernetes.yaml +cd deploy/helm ``` -This will display a **Hello world!** message when you hit the service endpoint in a browser. You can get the service endpoint ip address by executing the following command and grabbing the returned external ip address value: +### Example 1: Default + +Deploy into `hello-kubernetes-default` namespace with default "Hello world!" message. The `hello-kubernetes` app is exposed via a public Load Balancer on port 80 by default - note that this only works in cloud provider based Kubernetes offerings. ```bash -$ kubectl get service hello-kubernetes -``` +helm install --create-namespace --namespace hello-kubernetes-default hello-world ./hello-kubernetes -### Customise Message - -You can customise the message displayed by the `hello-kubernetes` container. Deploy using the hello-kubernetes.custom-message.yaml, which contains definitions for the service and deployment objects. - -In the definition for the deployment, add an `env` variable with the name of `MESSAGE`. The value you provide will be displayed as the custom message. - -```yaml -# hello-kubernetes.custom-message.yaml -apiVersion: v1 -kind: Service -metadata: - name: hello-kubernetes-custom -spec: - type: LoadBalancer - ports: - - port: 80 - targetPort: 8080 - selector: - app: hello-kubernetes-custom ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: hello-kubernetes-custom -spec: - replicas: 3 - selector: - matchLabels: - app: hello-kubernetes-custom - template: - metadata: - labels: - app: hello-kubernetes-custom - spec: - containers: - - name: hello-kubernetes - image: paulbouwer/hello-kubernetes:1.9 - ports: - - containerPort: 8080 - env: - - name: MESSAGE - value: I just deployed this on Kubernetes! +# get the LoadBalancer ip address. +kubectl get svc hello-kubernetes -n hello-kubernetes-default -o 'jsonpath={ .status.loadBalancer.ingress[0].ip }' ``` +### Example 2: Custom message + +Deploy into `hello-kubernetes-custom` namespace with "I just deployed this on Kubernetes!" message. The `hello-kubernetes` app is exposed via a public Load Balancer on port 80 by default - note that this only works in cloud provider based Kubernetes offerings. + ```bash -$ kubectl apply -f yaml/hello-kubernetes.custom-message.yaml -``` +helm install --create-namespace --namespace hello-kubernetes-custom hello-custom ./hello-kubernetes \ + --set message="I just deployed this on Kubernetes!" -### Specify Custom Port - -By default, the `hello-kubernetes` app listens on port `8080`. If you have a requirement for the app to listen on another port, you can specify the port via an env variable with the name of PORT. Remember to also update the `containers.ports.containerPort` value to match. - -Here is an example: - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: hello-kubernetes-custom -spec: - replicas: 3 - selector: - matchLabels: - app: hello-kubernetes-custom - template: - metadata: - labels: - app: hello-kubernetes-custom - spec: - containers: - - name: hello-kubernetes - image: paulbouwer/hello-kubernetes:1.9 - ports: - - containerPort: 80 - env: - - name: PORT - value: "80" +# get the LoadBalancer ip address. +kubectl get svc hello-kubernetes -n hello-kubernetes-custom -o 'jsonpath={ .status.loadBalancer.ingress[0].ip }' ``` -## Cutomize URL context path - -If you have an ingress that routes to a custom context path then you can customize the URL context path. The css files and the images will be loaded properly in that case. - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: hello-kubernetes-custom -spec: - replicas: 3 - selector: - matchLabels: - app: hello-kubernetes-custom - template: - metadata: - labels: - app: hello-kubernetes-custom - spec: - containers: - - name: hello-kubernetes - image: paulbouwer/hello-kubernetes:1.9 - ports: - - containerPort: 8080 - env: - - name: MESSAGE - value: I just deployed this on Kubernetes! - - name: CONTEXT_PATH - value: "/api/v1/hello-kubernetes/" +### Example 3: Ingress + +Deploy into `hello-kubernetes-ingress` namespace. This example assumes that an ingress has been deployed into the cluster and that the ingress has a path of `/app/hello-kubernetes/` mapped to the `hello-kubernetes` service. + +The `hello-kubernetes` app can be reached on the ip address of the ingress at the `/app/hello-kubernetes/` path. + +```bash +helm install --create-namespace --namespace hello-kubernetes-ingress hello-ingress ./hello-kubernetes \ + --set ingress.enabled=true \ + --set ingress.pathPrefix="/app/hello-kubernetes/" \ + --set service.type="ClusterIP" ``` ## Build Container Image diff --git a/deploy/helm/hello-kubernetes/.helmignore b/deploy/helm/hello-kubernetes/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/deploy/helm/hello-kubernetes/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deploy/helm/hello-kubernetes/Chart.yaml b/deploy/helm/hello-kubernetes/Chart.yaml new file mode 100644 index 00000000..6c9e33b7 --- /dev/null +++ b/deploy/helm/hello-kubernetes/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: hello-kubernetes +description: A demo application for a Kubernetes cluster. +type: application +version: 1.0.0 +appVersion: "1.10" diff --git a/deploy/helm/hello-kubernetes/templates/NOTES.txt b/deploy/helm/hello-kubernetes/templates/NOTES.txt new file mode 100644 index 00000000..e69de29b diff --git a/deploy/helm/hello-kubernetes/templates/_helpers.tpl b/deploy/helm/hello-kubernetes/templates/_helpers.tpl new file mode 100644 index 00000000..3e668aca --- /dev/null +++ b/deploy/helm/hello-kubernetes/templates/_helpers.tpl @@ -0,0 +1,14 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "hello-kubernetes.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "hello-kubernetes.selectorLabels" -}} +app.kubernetes.io/name: {{ include "hello-kubernetes.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/deploy/helm/hello-kubernetes/templates/deployment.yaml b/deploy/helm/hello-kubernetes/templates/deployment.yaml new file mode 100644 index 00000000..d6f937df --- /dev/null +++ b/deploy/helm/hello-kubernetes/templates/deployment.yaml @@ -0,0 +1,60 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.deployment.name }} +spec: + replicas: {{ .Values.deployment.replicaCount }} + selector: + matchLabels: + {{- include "hello-kubernetes.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "hello-kubernetes.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: {{ .Values.serviceAccount.name }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.deployment.container.image.repository }}:{{ .Values.deployment.container.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.deployment.container.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.deployment.container.port }} + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + env: + {{- if ne (.Values.deployment.container.port | int) (8080 | int) }} + - name: PORT + value: "{{ .Values.deployment.container.port }}" + {{- end }} + {{- if .Values.message }} + - name: MESSAGE + value: "{{ .Values.message }}" + {{- end }} + {{- if .Values.ingress.enabled }} + - name: CONTEXT_PATH + value: "{{ .Values.ingress.pathPrefix }}" + {{- end }} + {{- with .Values.deployment.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.deployment.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deploy/helm/hello-kubernetes/templates/service.yaml b/deploy/helm/hello-kubernetes/templates/service.yaml new file mode 100644 index 00000000..681cc985 --- /dev/null +++ b/deploy/helm/hello-kubernetes/templates/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.service.name }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "hello-kubernetes.selectorLabels" . | nindent 4 }} diff --git a/deploy/helm/hello-kubernetes/templates/serviceaccount.yaml b/deploy/helm/hello-kubernetes/templates/serviceaccount.yaml new file mode 100644 index 00000000..21c813d6 --- /dev/null +++ b/deploy/helm/hello-kubernetes/templates/serviceaccount.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccount.name }} diff --git a/deploy/helm/hello-kubernetes/values.yaml b/deploy/helm/hello-kubernetes/values.yaml new file mode 100644 index 00000000..d5da675c --- /dev/null +++ b/deploy/helm/hello-kubernetes/values.yaml @@ -0,0 +1,36 @@ +# Provide a custom message +message: "" + +ingress: + enabled: false + pathPrefix: "" + +service: + name: "hello-kubernetes" + type: LoadBalancer + port: 80 + +serviceAccount: + name: "hello-kubernetes" + +deployment: + replicaCount: 2 + name: "hello-kubernetes" + container: + image: + repository: "paulbouwer/hello-kubernetes" + tag: "1.9" # uses chart appVersion if not provided + pullPolicy: IfNotPresent + port: 8080 + + # Currently only linux images on amd64 architecture are supported - support for arm64 and windows/amd64 coming ... + nodeSelector: + kubernetes.io/os: linux + kubernetes.io/arch: amd64 + + resources: {} + + tolerations: [] + + affinity: {} + diff --git a/docs/deploy-using-helm.md b/docs/deploy-using-helm.md new file mode 100644 index 00000000..62aabe62 --- /dev/null +++ b/docs/deploy-using-helm.md @@ -0,0 +1,84 @@ +# Deploy using Helm + +A Helm chart to deploy the `hello-kubernetes` application. This chart will deploy the following resources: + +- ServiceAccount +- Service +- Deployment + +## Prerequisites + +- [Helm 3](https://v3.helm.sh/) +- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (authenticated to your Kubernetes cluster) +- [Kubernetes](https://kubernetes.io/) cluster + +## Configuration and installation + +The following table lists the configuration parameters of the hello-kubernetes chart and their default values. + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `message` | `string` | `""` | A custom message to display instead of the default. | +| `ingress.enabled` | `bool` | `false` | Indicate whether an ingress is being used. | +| `ingress.pathPrefix` | `string` | `""` | The path prefix configured in the ingress for the hello-kubernetes service.
Must be provided when ingress is used. | +| `service.name` | `string` | `"hello-kubernetes"` | The name of the service configured for the hello-kubernetes pods. | +| `service.type` | `string` | `"LoadBalancer"` | The service type. | +| `service.port` | `int` | `80` | The port exposed by the service. | +| `serviceAccount.name` | `string` | `"hello-kubernetes"` | The service account bound to the pods. | +| `deployment.replicaCount` | `int` | `2` | The number of replicas for the hello-kubernetes deployment. | +| `deployment.name` | `string` | `hello-kubernetes` | The name of the deployment containing the hello-kubernetes pods. | +| `deployment.container.image.repository` | `string` | `paulbouwer/hello-kubernetes` | The container image to run in the hello-kubernetes pods. | +| `deployment.container.image.tag` | `string` | `""` | The container image tag. If not specified, the chart's appVersion is used. | +| `deployment.container.image.pullPolicy` | `string` | `"IfNotPresent"` | The pull policy for the container image. | +| `deployment.container.port` | `int` | `"8080"` | The port that hello-kubernetes app listens on. | +| `deployment.nodeSelector` | `object` | `{"kubernetes.io/os":"linux", "kubernetes.io/arch":"amd64"}` | The node selector for the deployment. | +| `deployment.resources` | `object` | `{}` | The resource limits for the deployment. | +| `deployment.tolerations` | `object` | `[]` | The tolerations for the deployment. | +| `deployment.affinity` | `object` | `{}` | The affinity for the deployment. | + +### Installing the chart + +Ensure that you are in the chart directory in the repo, since you are referencing a local helm chart. + +```bash +cd deploy/helm +``` + +To install `hello-kubernets` via the Helm chart, use the following to: +- create the hello-kubernetes-default namespace +- deploy the chart located in the ./hello-kubernetes folder +- create a Helm release named hello-world + +```bash +helm install --create-namespace --namespace hello-kubernetes-default hello-world ./hello-kubernetes +``` + +You can override the values for the configuration parameter defined in the table above, either directly in the `hello-kubernetes/values.yaml` file, or via the `--set` switches. + +```bash +helm install --create-namespace --namespace hello-kubernetes-custom hello-custom ./hello-kubernetes \ + --set message="I just deployed this on Kubernetes!" +``` + +### Upgrading the chart + +Ensure that you are in the chart directory in the repo, since you are referencing a local helm chart. + +```bash +cd deploy/helm +``` + +You can modify the `hello-kubernetes` app by providing new values for the configuration parameter defined in the table above, either directly in the `hello-kubernetes/values.yaml` file, or via the `--set` switches. + +```bash +helm upgrade --namespace hello-kubernetes-custom hello-custom ./hello-kubernetes \ + --set message="This is a different message" +``` + +### Uninstalling the chart + +You can uninstall the `hello-kubernetes` app as follows: + +```bash +helm uninstall --namespace hello-kubernetes-custom hello-custom +``` \ No newline at end of file diff --git a/yaml/hello-kubernetes.custom-message.yaml b/yaml/hello-kubernetes.custom-message.yaml deleted file mode 100644 index c881d2bc..00000000 --- a/yaml/hello-kubernetes.custom-message.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: hello-kubernetes-custom -spec: - type: LoadBalancer - ports: - - port: 80 - targetPort: 8080 - selector: - app: hello-kubernetes-custom ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: hello-kubernetes-custom -spec: - replicas: 3 - selector: - matchLabels: - app: hello-kubernetes-custom - template: - metadata: - labels: - app: hello-kubernetes-custom - spec: - containers: - - name: hello-kubernetes - image: paulbouwer/hello-kubernetes:1.8 - ports: - - containerPort: 8080 - env: - - name: MESSAGE - value: I just deployed this on Kubernetes! diff --git a/yaml/hello-kubernetes.yaml b/yaml/hello-kubernetes.yaml deleted file mode 100644 index bad5b7d1..00000000 --- a/yaml/hello-kubernetes.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: hello-kubernetes -spec: - type: LoadBalancer - ports: - - port: 80 - targetPort: 8080 - selector: - app: hello-kubernetes ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: hello-kubernetes -spec: - replicas: 3 - selector: - matchLabels: - app: hello-kubernetes - template: - metadata: - labels: - app: hello-kubernetes - spec: - containers: - - name: hello-kubernetes - image: paulbouwer/hello-kubernetes:1.8 - ports: - - containerPort: 8080