-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #43 from cmason3/dev
Dev
- Loading branch information
Showing
11 changed files
with
197 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
## JinjaFx Server as a Container in Kubernetes | ||
|
||
JinjaFx Server will always be available in Docker Hub at [https://hub.docker.com/repository/docker/cmason3/jinjafx_server](https://hub.docker.com/repository/docker/cmason3/jinjafx_server) - the `latest` tag will always refer to the latest released version, although it is recommended to use explicit version tags. | ||
|
||
The following steps will run JinjaFx Server in a container using Kubernetes Ingress - Ingress is basically the same concept as Virtual Hosting (the default Ingress uses nginx), which works with HTTP and relies on the "Host" header to direct the request to the correct container. In a Virtual Hosting scenario you would typically point different DNS A records towards the same IP, but in our example we are using a Wildcard DNS entry for our whole Kubernetes cluster, e.g: | ||
|
||
``` | ||
*.{CLUSTER}.{DOMAIN}. 28800 IN A {HOST IP} | ||
``` | ||
|
||
This approach also allows us to use a single wildcard TLS certificate, which covers all containers under the cluster sub-domain. The example Kubernetes manifest (`kubernetes.yml`) assumes we will be activating the Web Log as well as using a GitHub backed repository to store JinjaFx DataTemplates. | ||
|
||
Once you have updated `kubernetes.yml` with your deployment specific values you would typically perform the following steps: | ||
|
||
### Generate Certificate Signing Request | ||
|
||
The following step is used to generate a CSR for your TLS certificiate. The Common Name (CN) isn't actually used as we will be using the "subjectAltName" field as it allows multiple values (you could also use something like Let's Encrypt here, but this is out of scope of this document): | ||
|
||
``` | ||
openssl req -nodes -newkey rsa:2048 -keyout ingress.key -out ingress.csr -subj "/CN={CN}/emailAddress={emailAddress}/O={O}/L={L}/ST={ST}/C={C}" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:*.{CLUSTER}.{DOMAIN}")) | ||
``` | ||
|
||
### Generate TLS Secret with Signed Certificate | ||
|
||
Once you have a signed certificate you would create a Kubernetes TLS secret called `ingress-tls` using the private key and signed public certificate: | ||
|
||
``` | ||
kubectl create secret tls ingress-tls --cert=ingress.crt --key=ingress.key | ||
``` | ||
|
||
### Save Environment Variables as Kubernetes Secrets | ||
|
||
To pass the GitHub Token as well as the key used for the Web Log we use Kubernetes secrets that we map into environment variables in the manifest: | ||
|
||
``` | ||
kubectl create secret generic jinjafx --from-literal=github-token={TOKEN} --from-literal=jfx-weblog-key={KEY} | ||
``` | ||
|
||
### Apply the Kubernetes Manifest | ||
|
||
``` | ||
kubectl apply -f kubernetes.yml | ||
``` | ||
|
||
If everything has worked then you should be able to point your web browser at `https://jinjafx.{CLUSTER}.{DOMAIN}` and it should present you with JinjaFx. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
--- | ||
apiVersion: networking.k8s.io/v1 | ||
kind: Ingress | ||
metadata: | ||
name: jinjafx-ingress | ||
spec: | ||
ingressClassName: public | ||
tls: | ||
- hosts: | ||
- "*.{CLUSTER}.{DOMAIN}" | ||
secretName: ingress-tls | ||
rules: | ||
- host: "jinjafx.{CLUSTER}.{DOMAIN}" | ||
http: | ||
paths: | ||
- path: / | ||
pathType: Prefix | ||
backend: | ||
service: | ||
name: jinjafx-service | ||
port: | ||
number: 8080 | ||
|
||
--- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: jinjafx-service | ||
spec: | ||
selector: | ||
app: jinjafx | ||
ports: | ||
- protocol: TCP | ||
port: 8080 | ||
|
||
--- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: jinjafx | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: jinjafx | ||
strategy: | ||
type: RollingUpdate | ||
rollingUpdate: | ||
maxUnavailable: 0 | ||
maxSurge: 1 | ||
template: | ||
metadata: | ||
labels: | ||
app: jinjafx | ||
spec: | ||
containers: | ||
- name: jinjafx | ||
image: docker.io/cmason3/jinjafx_server:latest | ||
args: ["-pandoc", "-github", "{OWNER}/{REPO}", "-weblog"] | ||
ports: | ||
- containerPort: 8080 | ||
readinessProbe: | ||
httpGet: { scheme: HTTP, port: 8080, path: /ping } | ||
initialDelaySeconds: 30 | ||
periodSeconds: 30 | ||
timeoutSeconds: 5 | ||
livenessProbe: | ||
httpGet: { scheme: HTTP, port: 8080, path: /ping } | ||
periodSeconds: 30 | ||
timeoutSeconds: 5 | ||
env: | ||
- name: TZ | ||
value: "Europe/London" | ||
- name: GITHUB_TOKEN | ||
valueFrom: | ||
secretKeyRef: | ||
name: jinjafx | ||
key: github-token | ||
- name: JFX_WEBLOG_KEY | ||
valueFrom: | ||
secretKeyRef: | ||
name: jinjafx | ||
key: jfx-weblog-key | ||
|
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
body { | ||
color: white; | ||
background: #000040; | ||
} | ||
pre { | ||
height: 100%; | ||
font-family: 'Fira Code', monospace; | ||
font-size: 14px; | ||
font-variant-ligatures: none; | ||
white-space: pre-wrap; | ||
word-break: break-all; | ||
overflow-y: hidden; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
(function() { | ||
let interval = 60; | ||
|
||
function scroll() { | ||
let e = document.getElementById('container'); | ||
e.scrollTop = e.scrollHeight; | ||
} | ||
|
||
function update() { | ||
var xHR = new XMLHttpRequest(); | ||
xHR.open("GET", '/logs?raw', true); | ||
|
||
xHR.onload = function() { | ||
if (this.status == 200) { | ||
document.getElementById('container').innerHTML = xHR.responseText; | ||
scroll(); | ||
setTimeout(update, interval * 1000); | ||
} | ||
else { | ||
document.getElementById('container').innerHTML = 'HTTP ERROR ' + this.status; | ||
} | ||
}; | ||
|
||
xHR.onerror = function() { | ||
document.getElementById('container').innerHTML = 'XMLHttpRequest ERROR'; | ||
setTimeout(update, interval * 1000); | ||
}; | ||
|
||
xHR.ontimeout = function() { | ||
document.getElementById('container').innerHTML = 'XMLHttpRequest TIMEOUT'; | ||
setTimeout(update, interval * 1000); | ||
}; | ||
|
||
xHR.timeout = 3000; | ||
xHR.send(); | ||
} | ||
|
||
window.onresize = scroll; | ||
window.onload = function() { | ||
update(); | ||
}; | ||
})(); |