Commit fab08dc5 authored by Dmytro Bogatov's avatar Dmytro Bogatov 💕

Merge branch '49-move-to-kubernetes-deployment' into 'master'

Resolve "Move to Kubernetes deployment"

Closes #49

See merge request dbogatov/status-site!23
parents d3e7fe3f 15f6fec2
Pipeline #2513 passed with stages
in 8 minutes and 39 seconds
......@@ -10,3 +10,7 @@ insert_final_newline = true
[*.yml]
indent_style = space
indent_size = 2
[*.yaml]
indent_style = space
indent_size = 2
......@@ -62,3 +62,6 @@ test/appsettings.*
*lock.json
docker-compose-*.yml
deployment/services/
deployment/config.yaml
......@@ -114,7 +114,7 @@ blc-docs:
- http-server documentation/out/ -p 80 > /dev/null &
- sleep 5
script:
- blc --filter-level 3 --input http://localhost -rog --exclude "*linkedin.*" --exclude "*doxygen.*" --exclude "*status.dbogatov.org*" --exclude "*github.com*" --exclude "*git.dbogatov.org*" | tee /dev/stderr | grep 'Finished!' | tail -1 | grep '0 broken.'
- blc --filter-level 3 --input http://localhost -rog --exclude "*linkedin.*" --exclude "*doxygen.*" --exclude "*status.dbogatov.org*" --exclude "*github.com*" --exclude "*git.dbogatov.org*" --exclude "*favicon*" --exclude "*fonts.gstatic.com*" | tee /dev/stderr | grep 'Finished!' | tail -1 | grep '0 broken.'
tags:
- docker
......@@ -140,6 +140,7 @@ release-app-docs:
release-debian:
stage: release
dependencies: []
image: dbogatov/docker-images:debian-latest
script:
- ./build.sh -f build-debian-package
......@@ -148,3 +149,15 @@ release-debian:
- debian/build/*
tags:
- docker
release-deployment:
stage: release
dependencies: []
image: dbogatov/docker-images:alpine-extras-latest
script:
- ./build.sh -f build-deployment
artifacts:
paths:
- deployment/config.yaml
tags:
- docker
......@@ -6,7 +6,7 @@ info:
Collects, processes and provides various data regarding the status of
the services.
version: "1.0.0"
host: status.makerchip.com
host: status.dbogatov.org
securityDefinitions:
apiauth:
type: apiKey
......
<!-- cSpell:ignore SDKJF 5432 SMDFKL sdahjdjhd _678 ajsdvbja asgfdk _876 ajhsvdjh yourdomain logmessage -->
<!-- cSpell:ignore SDKJF 5432 SMDFKL sdahjdjhd Kubernetes _678 ajsdvbja asgfdk _876 ajhsvdjh yourdomain logmessage -->
# Configuration
......@@ -28,7 +28,7 @@ Configuration is built in the `Startup` method and is available for [Dependency
## User perspective
It is required to supply `appsettings.yml` file as a *docker secret* launching the application with `docker stack deploy`.
It is required to supply `appsettings.yml` file as a *docker secret* when deploying the application to Kubernetes.
Please, refer to [Deployment section](/deployment/) to download example config and supply it as docker secret.
<!-- When [deploying with script](deployment/) it is possible to supply *example configuration* to get app up and running. -->
<!-- Then user is free to change the configuration and restart the app. -->
......
<!-- cSpell:ignore Kubernetes kubectl -->
# Deployment
## Deploy to swarm (preferred way)
## Kubernetes
Officially supported deployment strategy is using Kubernetes.
Please, see [Kubernetes docs](https://kubernetes.io/).
I have to assume some basic experience with Kubernetes.
You can deploy most of the system right away with the following command
kubectl apply -f https://git.dbogatov.org/dbogatov/status-site/-/jobs/artifacts/master/raw/deployment/config.yaml?job=release-deployment
You also need to supply your settings
kubectl create secret -n status-site generic appsettings.production.yml --from-file=/path/to/config.yaml
where your settings reside in `/path/to/config.yaml`.
This will download the config file from CI and apply it against your cluster.
It is recommended to inspect the file before applying it for security considerations.
This config creates a namespace `status-site` and creates resources within it.
It creates tuples deployment-service for each part of the system.
Components are designed to communicate with each other by names provided in config.
Each component also gets `appsettings` secret mounted as volume.
Lastly, database needs a stable persistent storage, so config include Persistent Volume Claim for 10 GB.
It is cluster administrator's responsibility to provide Volumes that meet claims.
You may adjust the claim's capacity if needed.
Finally, you may want to add ingress to make website accessible from the world.
By default, all services are not replicated (i.e. replication factor 1).
You may want to adjust this parameter.
Be careful, though.
The only components that are safe to replicate are `docs`, `ping` and `web`.
If `web` is replicated you may have issues with authorization, as one replica generated the cookie and another one does not recognize it.
I am working on this issue.
## LEGACY: Deploy to swarm (preferred way)
> This is the old way to deploy the system.
> It is not officially supported, but will likely work.
Status site is designed with swarm in mind.
The preferred way to deploy the system is using `docker stack deploy` command.
......
......@@ -290,6 +290,27 @@ build-for-compose () {
build-docker-images
}
## Deployment
build-deployment () {
cd $CWD/deployment
echo "Building deploy configs..."
if [ -z "$DOTNET_TAG" ]; then
DOTNET_TAG="local"
fi
./build-services.sh $DOTNET_TAG
rm -rf config.yaml
mv services/namespace.yaml config.yaml
cat services/**/*.yaml >> config.yaml
cat sources/volume-claim.yaml >> config.yaml
}
## DEBIAN PACKAGE
build-debian-package () {
......
#!/usr/bin/env bash
set -e
shopt -s globstar
SERVICES=("ping" "nginx" "docs" "daemons" "web" "database")
if [ $# -eq 0 ]
then
TAG="master"
else
TAG=$1
fi
# "49-move-to-kubernetes-deployment"
rm -rf services/
mkdir -p services
cp sources/namespace.yaml services/
for service in ${SERVICES[@]}
do
echo "Generating $service configs..."
mkdir -p services/$service
if [ "$service" != "database" ]
then
IMAGE="dbogatov/status-site:$service-$TAG"
FILE="deployment"
PORT="80"
else
IMAGE="postgres:9.6.3-alpine"
FILE="deployment-database"
PORT="5432"
fi
cp sources/service/{service,$FILE}.yaml services/$service
sed -i -e "s#__NAME__#$service#g" services/$service/{service,$FILE}.yaml
sed -i -e "s#__IMAGE__#$IMAGE#g" services/$service/{service,$FILE}.yaml
sed -i -e "s#__PORT__#$PORT#g" services/$service/{service,$FILE}.yaml
done
echo "Done!"
---
apiVersion: v1
kind: Namespace
metadata:
name: status-site
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: __NAME__
namespace: status-site
labels:
application: __NAME__
spec:
replicas: 1
selector:
matchLabels:
application: __NAME__
template:
metadata:
labels:
application: __NAME__
spec:
containers:
- name: __NAME__
image: __IMAGE__
imagePullPolicy: Always
volumeMounts:
- name: database-persistent-storage
mountPath: /var/lib/postgresql/data
env:
- name: POSTGRES_DB
value: "statussite"
- name: POSTGRES_USER
value: "statususer"
- name: POSTGRES_PASSWORD
value: "relyOn1InternalSwarmNetwork"
- name: PGDATA
value: "/var/lib/postgresql/data/db-files/"
volumes:
- name: database-persistent-storage
persistentVolumeClaim:
claimName: database-pv-claim
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: __NAME__
namespace: status-site
labels:
application: __NAME__
spec:
replicas: 1
selector:
matchLabels:
application: __NAME__
template:
metadata:
labels:
application: __NAME__
spec:
containers:
- name: __NAME__
image: __IMAGE__
imagePullPolicy: Always
volumeMounts:
- name: appsettings
mountPath: "/run/secrets/settings/"
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
volumes:
- name: appsettings
secret:
secretName: appsettings.production.yml
---
apiVersion: v1
kind: Service
metadata:
name: __NAME__
namespace: status-site
labels:
application: __NAME__
spec:
selector:
application: __NAME__
ports:
- port: __PORT__
targetPort: __PORT__
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: database-pv-claim
namespace: status-site
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
# storageClassName: do-block-storage
---
......@@ -40,7 +40,7 @@ namespace StatusMonitor.Daemons
var builder = new ConfigurationBuilder()
.AddYamlFile("appsettings.yml", optional: false) // read defaults first
.AddYamlFile(
$"{(env.IsProduction() ? "/run/secrets/" : "")}appsettings.{env.EnvironmentName.ToLower()}.yml",
$"{(env.IsProduction() ? "/run/secrets/settings/" : "")}appsettings.{env.EnvironmentName.ToLower()}.yml",
optional: env.IsStaging()
) // override with specific settings file
.AddJsonFile("version.json", optional: true)
......
......@@ -38,7 +38,7 @@ namespace StatusMonitor.Web
var builder = new ConfigurationBuilder()
.AddYamlFile("appsettings.yml", optional: false) // read defaults first
.AddYamlFile(
$"{(env.IsProduction() ? "/run/secrets/" : "")}appsettings.{env.EnvironmentName.ToLower()}.yml",
$"{(env.IsProduction() ? "/run/secrets/settings/" : "")}appsettings.{env.EnvironmentName.ToLower()}.yml",
optional: env.IsStaging()
) // override with specific settings file
.AddJsonFile("version.json", optional: true)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment