Deploying your website on Kubernetes

Kubernetes is a popular platform to perform containerized services deployment automatically, and we can manage containerized services more easily through kubernetes functionality.

Prerequisites

We use the latest kubernetes version as the example, and we’ll deploy three services: blog, sftp server and screen message web service.

  • OS: Ubuntu 18.04 LTS
  • Kubernetes: v1.13.1
  • Docker: v18.06
  • helm: v2.12

We are not walking through the kubernetes installation steps. You can find the installation guides on the Internet, for example, Kubernetes Setup and Deploy Kubernetes High Availability Cluster by kubeadm (Chinese). Kubernetes requires Docker (or others container system supported with CRI, Container Runtime Interface) for creating containers, please have Container Runtime installed in your server before starting install Kubernetes.

Custom Container Images

I used Dockerfile to build the container image because I have customized configuration files to have my personal information, theme configuration and google analytics tracking code in my hexo blog. For further information about writing a Dockerfile, you can refer to Dockerfile reference and Best practices for writing Dockerfiles.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Dockerfile for Hexo

FROM node:latest
RUN npm install hexo-cli -g
RUN hexo init hexo && cd hexo

WORKDIR /hexo
COPY config.yml _config.yml

# Plugins
RUN npm install hexo-generator-sitemap --save

# Install Dependencies and Generate Static Files
RUN npm install && hexo generate

EXPOSE 4000
CMD hexo server

After your Dockerfile was done, you can use this command to build and tag your image in your local image registry.

1
docker build ./hexo --tag aweimeow/hexo

Helm Charts Services

We can compose our services by the Helm. Helm is the package manager for Kubernetes, with pre-defined service configurations, like as Deployment, Service, and Ingress Controller. We can also modify Helm template to fit our need.

1
2
# helm create <your-service-name>
helm create hexo

Quick hints to modify your Helm chart

For most general usage, we only need to modify these values to make our services to run the Helm chart.

  • Container Image: Name of the image to boot containers
  • Protocol and Port: Assign what protocol and port used in containers
  • NodePort: Configure NodePort to make kubernetes do port forwarding from local port to container port.
  • Commands to run in the container: we may have several commands need to run in containers, we can define them in Helm chart.

Container Image

The configuration for container images located in values.yaml, you can update the value directly.

1
2
3
4
5
# value.yaml
image:
repository: aweimeow/hexo
tag: latest
pullPolicy: IfNotPresent

Protocol, Port and NodePort in values.yaml

The configuration for protocol and port that container used is located in values.yaml and templates/deployment.yaml. values.yaml defines the value of protocol and port, and templates/deployment.yaml refers the value from values.yaml.

In here, we are going to define a new value named nodeport. So it will expose container port on localhost’s port. In the following example, we configured a port forwarding function from localhost:30001 to container:4000.

1
2
3
4
5
# values.yaml
service:
type: NodePort
port: 4000
nodeport: 30001

In the meantime, we need to update templates/service.yaml, change spec.ports fields, we added a nodePort value, and this value referred to nodeport value that we defined in values.yaml, and this configuration enabled the port forwarding from localhost port to container port.

1
2
3
4
5
6
7
8
9
# templates/service.yaml
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
nodePort: {{ .Values.service.nodeport }}
targetPort: http
protocol: TCP
name: http

Command to run in the container

As my values.yaml defined, we opened port 4000 for the container, besides, we add command and args parameters to execute custom command for my container.

1
2
3
4
5
6
7
8
9
10
11
12
13
# templates/deployment.yaml
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["bash", "-xc"]
args:
- hexo generate && hexo server
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP

Deploying through Helm

You must have the Helm chart completed, and this is the time to deploy it into Kubernetes cluster. However, before we deploy, we need to grant administrator privilege to Helm.

Create tiller account

We can add a new user named tiller into the Kubernetes system by the following configuration, this configuration creates a user, and grant cluster-admin privilege to this user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# tiller.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system

Initialize Tiller POD to cluster

Tiller is the server side of Helm, and it runs in Kubernetes cluster and responsible for managing releases of our Helm charts, Helm runs as the client side and sends information to Tiller. We can use this command to initialize a tiller pod in the Kubernetes system.

1
helm init --service-account tiller

Deploying the Helm chart

When you’ve everything done, then it means you are ready to deploy your application in this cluster, with Helm command, you can deploy, delete, modify your application very easy.

1
2
3
4
helm install <helm-chart-dir-name>

# If you want your application run in the different namespace from default, you can add `-n` to assign namespace name when running the command.
helm install -n hexo-ns hexo/

Conclusion

This post demonstrates how to deploy (or upgrade) your services as the containerized application, and we go through with most straightforward web service, you can also try to deploy FTP service, mail service, and domain name service in your cluster. It will be more comfortable to maintain, deploy and scale in/out your services on Kubernetes.

Besides Hexo blog, I also deployed the SFTP service on my site, and mounted blog posts directory into SFTP service. Written an SFTP client script to sync and upload my blog posts automatically. It contains simple logistic to compare timestamp between the local side (my laptop) and the server side.

It’s pretty fun to build everything by hand, and I hope this post helps. Enjoy :)