A story that may make you happy if you create a Sorry Page image to put kubernetes into production

: christums_tree: This article is the 25th day article of WESEEK Advent Calendar 2020. : christmas_tree:

Introduction

You guys are using Kubernetes (hereafter k8s)! Recently, we have seen cases of adopting k8s even in production environments.

This time, it's not a positive dream story, but a slightly muddy story.

What is Sorry Page?

It is a page that tells the visitor that "the service is under maintenance" as shown in the image below.

The sample is the Sorry Page of GROWI.cloud of our service.

244138daa7d01a7766e52de0a380e4c4.png

** Promotion: ** GROWI.cloud is a service that makes it easy to get started with the wiki GROWI that you can write in Markdown. Please use GROWI.cloud because you can greatly reduce the trouble of building HackMD to use GROWI and simultaneous editing function.

Why did you decide to do it? (motivation)

When operating k8s, I think it is ideal to build a "service that does not fall" and a "service that does not require maintenance time". (Because such a mechanism is prepared)

However, there are times when it is safer to ** stop access from users once before performing work **. (Even if you try and error so as not to stop it)

On top of that, you also get the insurance security that there is a way to stop access in case of emergency.

Sorry Page How to make an image

Now let's prepare to create the image of Sorry Page.

Prepare the files with a directory structure like this.

.
├── README.md
├── assets
│   ├── css
│ │ └── CSS required for Sorry Page
│   ├── favicon.ico
│   ├── img
│ │ └── Images required for Sorry Page
│   ├── js
│ └── JS required for Sorry Page
├── docker
│   ├── Dockerfile
│   └── nginx
│       └── front.conf.template
├── index.html
└── kubernetes
    └── deployment.yaml

I will introduce the contents of various files.

For index.html and assets, write the HTML, CSS, JS, etc. of the Sorry Page itself.

Dockerfile is basically based on the nginx image and is COPY or ADD to include the nginx config file, index.html and assets.

docker/Dockerfile


# HOW TO BUILD:
#   $ docker build -t growi-cloud-sorry: -f docker/Dockerfile .
FROM weseek/nginx-auth-ldap:xxxxx

LABEL maintainer="XXX XXXX <xxxxxxx>"
LABEL description="This image is used for running to serve application files"
LABEL app=growi-cloud
LABEL role=release
LABEL component=nginx

COPY docker/nginx/front.conf.template /etc/nginx/conf.d/default.conf.template
COPY . /usr/share/nginx/html/

#Kubernetes health check file
RUN touch /usr/share/nginx/html/.health-check

front.conf.template has a simple setting that can deliver files under/usr/share/nginx/html.

nginx:docker/nginx/front.conf.template


# BASED ON nginx:1.13.6-alpine /etc/nginx/conf.d/default.conf

server {
    listen       80;
    server_name  localhost;

    gzip off;

    # Cache-Add control
    add_header Cache-Control "max-age=0, public";

    location / {
        root   /usr/share/nginx/html;

        # redirect to https if accessed via http
        if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }

        add_header Cache-Control "max-age=0, public";
        index index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Under the kubernetes directory is the manifest used to deploy the Sorry Page image to the k8s cluster.

The image part of deployment.yaml is replaced with example.com.

kubernetes/deployment.yaml


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: growi-cloud-sorry
  name: growi-cloud-sorry
  namespace: growi-cloud
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: growi-cloud-sorry
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: growi-cloud-sorry
    spec:
      containers:
      - image: example.com/growi/growi-cloud-sorry:master
        imagePullPolicy: Always
        name: growi-cloud-sorry-demo
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      restartPolicy: Always

Build image

I wrote it as a comment in Dockerfile, but run docker build at the top of the directory for the created project

$ docker build -t growi-cloud-sorry -f docker/Dockerfile .

Deploy to a k8s cluster and direct to Sorry Page

The assumed configuration is as follows. Although various omissions are made, it is assumed that the access lead to the service is passed in the flow of User-> Ingress-> Service-> Pod.

Step1.png

Apply deployment.yaml to the k8s cluster to deploy the Sorry Page image

kubectl apply -f kubernetes/deployment.yaml

Once reflected, you will be able to change to the GROWI.cloud Sorry Page Pod as shown in the figure below.

002.png

In this state, rewrite the contents of GROWI.cloud Service with kubectl edit ... to change the destination.

003.png

Service rewrites the selector part to growi-cloud-sorry.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: growi-cloud # <-Growi here-cloud-Rewrite to sorry
(abridgement)...

How to switch access destinations

This seems to be very controversial, but if you rewrite GKE Ingress, it will take some time to reflect it, so I think it is better to implement the switching method according to the application.

Finally

This time, I introduced the Sorry Page image in the following flow.

  1. Sorry Page How to make an image
  2. How to deploy your Sorry Page image to a k8s cluster
  3. How to switch the access destination to Sorry Page Pod

It may be helpful in case of emergency, but I would like to aim to operate the service without relying on the Sorry Page image as much as possible: christus_tree:

Recommended Posts

A story that may make you happy if you create a Sorry Page image to put kubernetes into production
What to do if you accidentally create a model
If you want to make a Java application a Docker image, it is convenient to use jib.
We have released a service that allows you to easily create chats!
A story that was embarrassing to give anison file to the production environment
If you want to make a zip file with Ruby, it's rubyzip.
[Swift] If you want to use a URL that includes Japanese, use addingPercentEncoding.