stack_car 0.9.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +64 -1
- data/lib/stack_car.rb +1 -0
- data/lib/stack_car/cli.rb +112 -36
- data/lib/stack_car/dot_rc.rb +25 -0
- data/lib/stack_car/version.rb +1 -1
- data/stack_car.gemspec +1 -0
- data/templates/.dockerignore.erb +2 -2
- data/templates/.env.development.erb +2 -0
- data/templates/.env.erb +15 -16
- data/templates/.gitlab-ci.yml.erb +94 -62
- data/templates/Dockerfile.base.erb +28 -19
- data/templates/Dockerfile.erb +26 -7
- data/templates/chart-fcrepo/fcrepo-deploy.yaml +63 -0
- data/templates/chart-fcrepo/fcrepo-env-cm.yaml +8 -0
- data/templates/chart-fcrepo/fcrepo-env-secret.yaml.tt +10 -0
- data/templates/chart-fcrepo/fcrepo-pvc.yaml +20 -0
- data/templates/chart-fcrepo/fcrepo-svc.yaml +19 -0
- data/templates/chart-sidekiq/sidekiq-deploy.yaml +80 -0
- data/templates/chart/.gitignore +3 -0
- data/templates/chart/.helmignore +23 -0
- data/templates/chart/Chart.yaml.tt +29 -0
- data/templates/chart/README.md +223 -0
- data/templates/chart/bin/check_sidekiq.rb +0 -0
- data/templates/chart/bin/decrypt +17 -0
- data/templates/chart/bin/deploy +14 -0
- data/templates/chart/bin/encrypt +15 -0
- data/templates/chart/bin/remove +15 -0
- data/templates/chart/sample-values.yaml.tt +138 -0
- data/templates/chart/templates/_helpers.tpl.tt +85 -0
- data/templates/chart/templates/rails-env-cm.yaml.tt +47 -0
- data/templates/chart/templates/rails-env-secret.yaml +10 -0
- data/templates/chart/templates/rails-pvc-shared.yml +20 -0
- data/templates/chart/templates/setup-job.yaml +73 -0
- data/templates/chart/templates/web-deploy.yaml +67 -0
- data/templates/chart/templates/web-ing-wildcard.yaml +20 -0
- data/templates/chart/templates/web-ing.yaml +20 -0
- data/templates/chart/templates/web-svc.yaml +20 -0
- data/templates/database.yml.erb +10 -10
- data/templates/docker-compose.yml.erb +53 -12
- data/templates/env.conf.erb +11 -11
- data/templates/nginx.sh.erb +17 -0
- metadata +47 -10
- data/templates/docker-compose.ci.yml.erb +0 -87
- data/templates/docker-compose.production.yml.erb +0 -26
@@ -0,0 +1,10 @@
|
|
1
|
+
---
|
2
|
+
apiVersion: v1
|
3
|
+
kind: Secret
|
4
|
+
metadata:
|
5
|
+
name: {{ template "app.fcrepo-env.name" . }}
|
6
|
+
data:
|
7
|
+
DATABASE_PASSWORD: {{ .Values.env.secret.DATABASE_PASSWORD | b64enc }}
|
8
|
+
<% if options[:postgres] %>
|
9
|
+
JAVA_OPTS: {{ printf "-Dfcrepo.modeshape.configuration=\"classpath:/config/jdbc-postgresql/repository.json\" -Dfcrepo.postgresql.host=\"%s\" -Dfcrepo.postgresql.username=\"%s\" -Dfcrepo.postgresql.password=\"%s\" -Dfcrepo.object.directory=\"/data/objects\" -Dfcrepo.binary.directory=\"/data/binaries\"" ( include "app.postgres.name" . ) .Values.env.configmap.DATABASE_USER .Values.env.secret.DATABASE_PASSWORD | b64enc }}
|
10
|
+
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
kind: PersistentVolumeClaim
|
3
|
+
apiVersion: v1
|
4
|
+
metadata:
|
5
|
+
name: {{ template "app.fcrepo.name" . }}
|
6
|
+
labels:
|
7
|
+
app: {{ template "app.name" . }}
|
8
|
+
chart: {{ template "app.chart" . }}
|
9
|
+
release: {{ .Release.Name }}
|
10
|
+
heritage: {{ .Release.Service }}
|
11
|
+
component: fcrepo
|
12
|
+
spec:
|
13
|
+
accessModes:
|
14
|
+
- ReadWriteOnce
|
15
|
+
resources:
|
16
|
+
requests:
|
17
|
+
storage: {{ .Values.fcrepo.storage.size }}
|
18
|
+
{{- if .Values.fcrepo.storage.className }}
|
19
|
+
storageClassName: "{{ .Values.fcrepo.storage.ClassName }}"
|
20
|
+
{{- end }}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
apiVersion: v1
|
3
|
+
kind: Service
|
4
|
+
metadata:
|
5
|
+
name: {{ template "app.fcrepo.name" . }}
|
6
|
+
labels:
|
7
|
+
app: {{ template "app.name" . }}
|
8
|
+
chart: {{ template "app.chart" . }}
|
9
|
+
release: {{ .Release.Name }}
|
10
|
+
heritage: {{ .Release.Service }}
|
11
|
+
component: fcrepo
|
12
|
+
spec:
|
13
|
+
ports:
|
14
|
+
- protocol: TCP
|
15
|
+
port: 8080
|
16
|
+
selector:
|
17
|
+
app: {{ template "app.name" . }}
|
18
|
+
release: {{ .Release.Name }}
|
19
|
+
component: fcrepo
|
@@ -0,0 +1,80 @@
|
|
1
|
+
---
|
2
|
+
apiVersion: apps/v1
|
3
|
+
kind: Deployment
|
4
|
+
metadata:
|
5
|
+
name: {{ template "app.sidekiq.name" . }}
|
6
|
+
labels:
|
7
|
+
app: {{ template "app.name" . }}
|
8
|
+
chart: {{ template "app.chart" . }}
|
9
|
+
release: {{ .Release.Name }}
|
10
|
+
heritage: {{ .Release.Service }}
|
11
|
+
component: sidekiq
|
12
|
+
spec:
|
13
|
+
replicas: {{ .Values.sidekiq.replicas }}
|
14
|
+
selector:
|
15
|
+
matchLabels:
|
16
|
+
app: {{ template "app.name" . }}
|
17
|
+
release: {{ .Release.Name }}
|
18
|
+
component: sidekiq
|
19
|
+
template:
|
20
|
+
metadata:
|
21
|
+
labels:
|
22
|
+
app: {{ template "app.name" . }}
|
23
|
+
release: {{ .Release.Name }}
|
24
|
+
component: sidekiq
|
25
|
+
annotations:
|
26
|
+
checksum/rails-env-cm: {{ include (print $.Template.BasePath "/rails-env-cm.yaml") . | sha256sum }}
|
27
|
+
checksum/rails-env-secret: {{ include (print $.Template.BasePath "/rails-env-secret.yaml") . | sha256sum }}
|
28
|
+
spec:
|
29
|
+
restartPolicy: Always
|
30
|
+
terminationGracePeriodSeconds: {{ .Values.sidekiq.timeout | add 5 }}
|
31
|
+
{{- if .Values.rails.imagePullSecrets }}
|
32
|
+
imagePullSecrets:
|
33
|
+
{{ toYaml .Values.rails.imagePullSecrets }}
|
34
|
+
{{- end }}
|
35
|
+
volumes:
|
36
|
+
- name: shared
|
37
|
+
persistentVolumeClaim:
|
38
|
+
claimName: {{ template "app.rails-env.name" . }}-shared
|
39
|
+
containers:
|
40
|
+
- name: sidekiq
|
41
|
+
image: {{ .Values.rails.image.repository }}:{{ .Values.rails.image.tag }}
|
42
|
+
imagePullPolicy: Always
|
43
|
+
command: ["/bin/bash"]
|
44
|
+
args:
|
45
|
+
- "-l"
|
46
|
+
- "-c"
|
47
|
+
- "bundle exec sidekiq"
|
48
|
+
# livenessProbe:
|
49
|
+
# exec:
|
50
|
+
# command:
|
51
|
+
# - ./bin/rails runner ./chart/bin/check_sidekiq.rb
|
52
|
+
# initialDelaySeconds: 30
|
53
|
+
# Use sub-path for individual folders
|
54
|
+
volumeMounts:
|
55
|
+
- mountPath: /home/app/webapp/tmp/imports
|
56
|
+
name: shared
|
57
|
+
subPath: import_path
|
58
|
+
- mountPath: /home/app/webapp/tmp/exports
|
59
|
+
name: shared
|
60
|
+
subPath: export_path
|
61
|
+
- mountPath: /home/app/webapp/tmp/derivatives_path
|
62
|
+
name: shared
|
63
|
+
subPath: derivatives_path
|
64
|
+
- mountPath: /home/app/webapp/tmp/uploads
|
65
|
+
name: shared
|
66
|
+
subPath: upload_path
|
67
|
+
- mountPath: /home/app/webapp/public/uploads
|
68
|
+
name: shared
|
69
|
+
subPath: uploads
|
70
|
+
- mountPath: /home/app/webapp/public/assets
|
71
|
+
name: shared
|
72
|
+
subPath: assets
|
73
|
+
- mountPath: /home/app/webapp/public/branding
|
74
|
+
name: shared
|
75
|
+
subPath: branding
|
76
|
+
envFrom:
|
77
|
+
- configMapRef:
|
78
|
+
name: {{ template "app.rails-env.name" . }}
|
79
|
+
- secretRef:
|
80
|
+
name: {{ template "app.rails-env.name" . }}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Patterns to ignore when building packages.
|
2
|
+
# This supports shell glob matching, relative path matching, and
|
3
|
+
# negation (prefixed with !). Only one pattern per line.
|
4
|
+
.DS_Store
|
5
|
+
# Common VCS dirs
|
6
|
+
.git/
|
7
|
+
.gitignore
|
8
|
+
.bzr/
|
9
|
+
.bzrignore
|
10
|
+
.hg/
|
11
|
+
.hgignore
|
12
|
+
.svn/
|
13
|
+
# Common backup files
|
14
|
+
*.swp
|
15
|
+
*.bak
|
16
|
+
*.tmp
|
17
|
+
*~
|
18
|
+
# Various IDEs
|
19
|
+
.project
|
20
|
+
.idea/
|
21
|
+
*.tmproj
|
22
|
+
server.pem
|
23
|
+
server.key
|
@@ -0,0 +1,29 @@
|
|
1
|
+
apiVersion: v1
|
2
|
+
appVersion: "0.0.1"
|
3
|
+
description: A Helm chart for <%= @project_name %>
|
4
|
+
name: <%= @project_name %>
|
5
|
+
version: 0.0.1
|
6
|
+
dependencies:
|
7
|
+
<%- if options[:solr] %>
|
8
|
+
- name: solr
|
9
|
+
version: 1.3.3
|
10
|
+
repository: https://storage.googleapis.com/kubernetes-charts-incubator
|
11
|
+
<%- end %>
|
12
|
+
<%- if options[:redis] %>
|
13
|
+
- name: redis
|
14
|
+
version: 10.3.1
|
15
|
+
repository: https://kubernetes-charts.storage.googleapis.com/
|
16
|
+
condition: redis.enabled
|
17
|
+
<%- end %>
|
18
|
+
<%- if options[:postgres] %>
|
19
|
+
- name: postgresql
|
20
|
+
version: 8.1.2
|
21
|
+
repository: https://kubernetes-charts.storage.googleapis.com/
|
22
|
+
condition: postgresql.enabled
|
23
|
+
<%- end %>
|
24
|
+
<%- if options[:mysql] %>
|
25
|
+
- name: mariadb
|
26
|
+
version: 5.x.x
|
27
|
+
repository: https://kubernetes-charts.storage.googleapis.com/
|
28
|
+
condition: mariadb.enabled
|
29
|
+
<%- end %>
|
@@ -0,0 +1,223 @@
|
|
1
|
+
Helm Chart
|
2
|
+
==========
|
3
|
+
|
4
|
+
This is a Rails Helm Chart which can be used to deploy a Rails instance to a Kubernetes cluster.
|
5
|
+
|
6
|
+
# Requirements
|
7
|
+
|
8
|
+
* helm
|
9
|
+
```
|
10
|
+
brew install helm
|
11
|
+
```
|
12
|
+
|
13
|
+
* kubernetes
|
14
|
+
Kubectl is the command line tool for controlling Kubernetes clusters. It is available via (https://docs.docker.com/docker-for-mac/)[Docker for Mac]
|
15
|
+
|
16
|
+
Alternatively:
|
17
|
+
```
|
18
|
+
brew install kubectl
|
19
|
+
```
|
20
|
+
|
21
|
+
# Getting Started Locally using Docker for Mac
|
22
|
+
|
23
|
+
## Setup
|
24
|
+
|
25
|
+
Install Docker for Mac (DfM)
|
26
|
+
|
27
|
+
Enable the Kubernetes Cluster in the DfM Settings
|
28
|
+
|
29
|
+
In the menu bar item for DfM you'll 'Kubernetes', this will list the available clusters. For local deployment make sure docker-desktop is selected.
|
30
|
+
|
31
|
+
## KubeConfig
|
32
|
+
|
33
|
+
Kubernetetes creates a config file at `~/.kube/config`. When we come to setting up access to external clusters, we will be editing this file. That will add clusters to the DfM Kubernetes list. Remember that if you are running deployment actions using helm or kubectl they will use the cluster selected in that list, so if you were deploying to a production server yesterday, that will still be selected. It is a good practice to run `kubectl cluster-info` or `kubectl config current-context` before starting any deployment to make sure you are deploying to the right cluster.
|
34
|
+
|
35
|
+
## GitLab Secret
|
36
|
+
|
37
|
+
To pull images from a private registry, you'll need a secret
|
38
|
+
|
39
|
+
For GitLab, create a Personal Access Token in GitLab with read access.
|
40
|
+
|
41
|
+
Create your secret (called gitlab) in kubectl, substituting the items in {} with your data:
|
42
|
+
```
|
43
|
+
create secret docker-registry gitlab --docker-server=https://registry.gitlab.com --docker-username={YOUR USERNAME} --docker-password={PERSONAL ACCESS TOKEN} --docker-email={YOUR EMAIL} --namespace {NAMESPACE eg. hyku-staging}
|
44
|
+
```
|
45
|
+
|
46
|
+
Reference the secret in `imagePullSecrets`, see the sample.yamnl file for an example.
|
47
|
+
|
48
|
+
For other private registries, please consult their documentation on access tokens.
|
49
|
+
|
50
|
+
## TLS Secret
|
51
|
+
|
52
|
+
We also need to setup a secret for TLS certificates.
|
53
|
+
|
54
|
+
```
|
55
|
+
# this command will generate self signed server certificate and key: server.pem, server.key
|
56
|
+
# key and cert are stored in Secret object named `demoapp-puma-tls`.
|
57
|
+
# you can confirm this object by `kubectl describe secret demoapp-puma-tls`
|
58
|
+
export COMMON_NAME=localhost
|
59
|
+
openssl req -new -x509 -nodes -keyout server.key -days 3650 \
|
60
|
+
-subj "/CN=${COMMON_NAME}" \
|
61
|
+
-extensions v3_req \
|
62
|
+
-config <(cat openssl.conf | sed s/\${COMMON_NAME}/$COMMON_NAME/) > server.pem
|
63
|
+
```
|
64
|
+
|
65
|
+
NOTE: you may need change openssl.conf to point to your local path, eg. /System/Library/OpenSSL/openssl.cnf
|
66
|
+
|
67
|
+
```
|
68
|
+
kubectl create secret tls demoapp-puma-tls --key server.key --cert server.pem
|
69
|
+
```
|
70
|
+
|
71
|
+
## Add Helm Chart Repository
|
72
|
+
|
73
|
+
We are going to need to install a couple of things on our local cluster. For this we need to install charts from the Helm stable chart repository.
|
74
|
+
|
75
|
+
One off installation of the repository:
|
76
|
+
```
|
77
|
+
helm repo add stable https://kubernetes-charts.storage.googleapis.com
|
78
|
+
```
|
79
|
+
|
80
|
+
## Install NFS
|
81
|
+
|
82
|
+
To run locally and use NFS file mounts we'll need an NFS server:
|
83
|
+
|
84
|
+
Helm install to run the nfs server on kubernetes:
|
85
|
+
```
|
86
|
+
helm install stable/nfs-server-provisioner --generate-name
|
87
|
+
```
|
88
|
+
|
89
|
+
NOTE: you can substitute --generate-name with --name followed by your chosen name for the resource
|
90
|
+
|
91
|
+
NOTE: stop / remove it with helm uninstall {name} --namespace default
|
92
|
+
|
93
|
+
### Ingress
|
94
|
+
|
95
|
+
To run locally we'll need an Ingress controller - this provides us with the ability to access the application on the web:
|
96
|
+
|
97
|
+
Helm install to run the ingress controller on kubernetes:
|
98
|
+
```
|
99
|
+
helm install stable/nginx-ingress --generate-name
|
100
|
+
```
|
101
|
+
|
102
|
+
NOTE: you can substitute --generate-name with --name followed by your chosen name for the resource
|
103
|
+
|
104
|
+
NOTE: stop / remove it with helm uninstall {name} --namespace default
|
105
|
+
|
106
|
+
## Values
|
107
|
+
|
108
|
+
When deploying the Helm chart we will provide a yaml file containing various configurations choices.
|
109
|
+
|
110
|
+
A sample values file is provided to give defaults: `sample.yaml`. Copy this file (eg. to development-values.yamnl) and change values as appropriate.
|
111
|
+
|
112
|
+
**Handling values files**
|
113
|
+
|
114
|
+
Since values files are likely to contain sensitive information like API keys, they are included in `.gitignore` and MUST NOT be added to the repository. Encrypt the file before committing them to the repository, using the provided bin scripts in this directory.
|
115
|
+
|
116
|
+
Example workflow (given values file is already created):
|
117
|
+
- Edit values file
|
118
|
+
- `chart/bin/encrypt staging <keybase-team-name>`
|
119
|
+
- This command will create `staging-values.yaml.enc`
|
120
|
+
- `git add staging-values.yaml.enc`
|
121
|
+
- Commit and push
|
122
|
+
|
123
|
+
When pulling down a repo or branch, you will need to start by decrypting.
|
124
|
+
|
125
|
+
Example:
|
126
|
+
- `chart/bin/decrypt staging`
|
127
|
+
|
128
|
+
## Deploy using Helm
|
129
|
+
|
130
|
+
From ./chart/
|
131
|
+
|
132
|
+
```
|
133
|
+
./bin/deploy development latest
|
134
|
+
```
|
135
|
+
|
136
|
+
Open demoapp in browser
|
137
|
+
```
|
138
|
+
open locaallhost
|
139
|
+
```
|
140
|
+
|
141
|
+
## Cleanup
|
142
|
+
helm uninstall development --namespace REPO_NAME
|
143
|
+
|
144
|
+
eg. `helm uninstall development --namespace project-env`
|
145
|
+
|
146
|
+
Tip: add the --dry-run to see what will be deleted
|
147
|
+
|
148
|
+
## Kubernetes Dashboard
|
149
|
+
|
150
|
+
Kubernetes provides a web-based dashboard for viewing and managing the deployed resources.
|
151
|
+
|
152
|
+
# Install it:
|
153
|
+
```
|
154
|
+
helm install stable/kubernetes-dashboard --generate-name
|
155
|
+
```
|
156
|
+
|
157
|
+
Make a note of the start command printed on install. It includes the release name (eg. kubernetes-dashboard-1579333192).
|
158
|
+
|
159
|
+
Tip: You can replace --generate-name with --name and supply a name for the release to give you a stable name.
|
160
|
+
|
161
|
+
Start it:
|
162
|
+
```
|
163
|
+
(RELEASE_NAME will be the value from your installation - find it with helm ls)
|
164
|
+
|
165
|
+
export POD_NAME=$(kubectl get pods -n default -l "app=kubernetes-dashboard,release=RELEASE_NAME" -o jsonpath="{.items[0].metadata.name}")
|
166
|
+
echo https://127.0.0.1:8443/
|
167
|
+
kubectl -n default port-forward $POD_NAME 8443:8443
|
168
|
+
```
|
169
|
+
|
170
|
+
Open it:
|
171
|
+
```
|
172
|
+
https://127.0.0.1:8443/
|
173
|
+
```
|
174
|
+
|
175
|
+
It will ask you to login by one of two methods. Opt for 'access token'.
|
176
|
+
|
177
|
+
Print your access token in a console as follwos, and then copy paste it into the token box on the dashboard login:
|
178
|
+
```
|
179
|
+
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | awk '/^deployment-controller-token-/{print $1}') | awk '$1=="token:"{print $2}'
|
180
|
+
```
|
181
|
+
|
182
|
+
# Deploying to Staging and Production clusters
|
183
|
+
|
184
|
+
Staging and Production deployment require the following steps:
|
185
|
+
|
186
|
+
1. Add the necessary kube config for your remote cluster
|
187
|
+
|
188
|
+
2. Switch kubernetes context
|
189
|
+
|
190
|
+
Either using the list in DfM Kubernetes, or with the following:
|
191
|
+
|
192
|
+
```
|
193
|
+
# check the current context
|
194
|
+
kubectl config current-context
|
195
|
+
# find the context you want in the list
|
196
|
+
kubectl config get-contexts
|
197
|
+
# switch
|
198
|
+
kubectl config use-context CONTEXT_NAME
|
199
|
+
```
|
200
|
+
|
201
|
+
3. Setup the *-values.yaml for staging or production
|
202
|
+
|
203
|
+
4. Deploy
|
204
|
+
|
205
|
+
```
|
206
|
+
# bin/deploy ENVIRONMENT TAG
|
207
|
+
bin/deploy staging latest
|
208
|
+
```
|
209
|
+
|
210
|
+
NOTE: the TAG will be used to pull the latest image from the GitLab repository. If the code has changed, make sure it's been pushed and the tagged image in the repository updated.
|
211
|
+
|
212
|
+
The namespace will be set to the git repository name, eg. project-env. Make sure the namespace exists in your cluster. Create it with `kubectl create namespace project-env`
|
213
|
+
|
214
|
+
# Troubleshooting
|
215
|
+
|
216
|
+
The Kubernetes Dashboard (locally) allows you to view logs and access a shell session. If problems occur during deployment, there is an event history that can provide more information.
|
217
|
+
|
218
|
+
There are equivalent kubectl commands for logs and accessing a shell, eg.
|
219
|
+
|
220
|
+
```
|
221
|
+
kubectl kubectl exec -it POD --namespace NAMESPACE -- /bin/bash
|
222
|
+
kubectl kubectl logs POD --namespace NAMESPACE
|
223
|
+
```
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
3
|
+
cd $DIR/../../chart
|
4
|
+
|
5
|
+
echo $DIR
|
6
|
+
|
7
|
+
REPO=$(basename $(git config --get remote.origin.url))
|
8
|
+
NAMESPACE=${REPO%.git}
|
9
|
+
|
10
|
+
if [ -z "$1" ]
|
11
|
+
then
|
12
|
+
echo './chart/bin/decrypt ENVIRONMENT'
|
13
|
+
exit 1
|
14
|
+
fi
|
15
|
+
|
16
|
+
keybase decrypt -i $1-values.yaml.enc -o $1-values.yaml
|
17
|
+
|