Skip to content

Commit 89e6e62

Browse files
Merge pull request #2 from StackEng/vakil/ASCN-202
ASCN-202: Local k8s / docker / cnab for opserver
2 parents b14819c + b83fae4 commit 89e6e62

18 files changed

+996
-6
lines changed

Dockerfile

+8-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ WORKDIR /app/src/Opserver.Web
2222
RUN dotnet publish -c Release -o publish
2323

2424
# Build runtime image
25-
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS web
25+
FROM cr.stackoverflow.software/so-aspnet:6.0-jammy-chiseled AS base
26+
27+
USER $APP_UID
28+
2629
WORKDIR /app
27-
COPY --from=web-publish /app/src/Opserver.Web/publish ./
30+
COPY --chown=app:app --from=web-publish /app/src/Opserver.Web/publish ./
31+
COPY --chown=app:app --from=web-publish /app/src/Opserver.Web/opserverSettings.json ./Config/opserverSettings.json
32+
33+
2834
ENTRYPOINT ["dotnet", "Opserver.Web.dll"]

charts/opserver/.helmignore

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
*.orig
18+
*~
19+
# Various IDEs
20+
.project
21+
.idea/
22+
*.tmproj
23+
.vscode/
24+
.github/CODEOWNERS

charts/opserver/Chart.yaml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: v2
2+
name: opserver
3+
description: A Helm chart for Kubernetes
4+
5+
# A chart can be either an 'application' or a 'library' chart.
6+
#
7+
# Application charts are a collection of templates that can be packaged into versioned archives
8+
# to be deployed.
9+
#
10+
# Library charts provide useful utilities or functions for the chart developer. They're included as
11+
# a dependency of application charts to inject those utilities and functions into the rendering
12+
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
13+
type: application
14+
15+
# This is the chart version. This version number should be incremented each time you make changes
16+
# to the chart and its templates, including the app version.
17+
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18+
version: 1.0.1
19+
20+
# This is the version number of the application being deployed. This version number should be
21+
# incremented each time you make changes to the application. Versions are not expected to
22+
# follow Semantic Versioning. They should reflect the version the application is using.
23+
# It is recommended to use it with quotes.
24+
appVersion: "0.0.1" # we don't use this field
+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: {{ .Release.Name }}
5+
namespace: {{ .Release.Namespace }}
6+
spec:
7+
replicas: {{ .Values.replicaCount }}
8+
selector:
9+
matchLabels:
10+
service: {{ .Release.Name }}
11+
template:
12+
metadata:
13+
labels:
14+
service: {{ .Release.Name }}
15+
spec:
16+
serviceAccountName: {{ .Release.Name }}
17+
containers:
18+
- name: opserver
19+
image: "{{ .Values.images.containerRegistry }}/{{ .Values.images.opserver.name }}:{{ .Values.images.opserver.tag }}"
20+
resources:
21+
requests:
22+
memory: {{ .Values.requests.memory }}
23+
cpu: {{ .Values.requests.cpu }}
24+
limits:
25+
memory: {{ .Values.limits.memory }}
26+
securityContext:
27+
allowPrivilegeEscalation: false
28+
capabilities:
29+
drop:
30+
- ALL
31+
readOnlyRootFilesystem: true
32+
runAsNonRoot: true
33+
volumeMounts:
34+
- name: writable-tmp #need our own read-write enabled temp directory because aspnet spills large requests over to disk
35+
mountPath: /mnt/tmp
36+
imagePullPolicy: {{ .Values.image.pullPolicy }}
37+
ports:
38+
- containerPort: {{ .Values.kestrel.endPoints.http.containerPort }}
39+
livenessProbe:
40+
httpGet:
41+
path: /health-checks/live
42+
port: {{ .Values.kestrel.endPoints.http.containerPort }}
43+
initialDelaySeconds: 10
44+
periodSeconds: 10
45+
timeoutSeconds: 2
46+
failureThreshold: 3
47+
readinessProbe:
48+
httpGet:
49+
path: /health-checks/ready
50+
port: {{ .Values.kestrel.endPoints.http.containerPort }}
51+
initialDelaySeconds: 10
52+
periodSeconds: 1
53+
successThreshold: 3
54+
volumeMounts:
55+
- name: writable-tmp
56+
mountPath: /mnt/tmp
57+
58+
env:
59+
- name: NODE_IP
60+
valueFrom:
61+
fieldRef:
62+
fieldPath: status.hostIP
63+
64+
- name: DOTNET_EnableDiagnostics
65+
value: "0"
66+
67+
- name: ASPNETCORE_ENVIRONMENT
68+
value: {{ .Values.aspnetcoreEnvironment }}
69+
- name: PRODUCT
70+
value: {{ .Values.product }}
71+
72+
- name: EXCEPTIONAL__STORE__APPLICATIONNAME
73+
value: "{{ .Release.Name }}"
74+
- name: EXCEPTIONAL__STORE__TYPE
75+
value: "{{ .Values.exceptional.store.type }}"
76+
77+
- name: DATADOG__AGENTHOST
78+
value: "{{- if eq .Values.datadog.agentHost "127.0.0.1"}}$(NODE_IP){{- else}}{{ .Values.datadog.agentHost }}{{- end}}"
79+
- name: DATADOG__AGENTPORT
80+
value: "{{ .Values.datadog.agentPort }}"
81+
82+
# this exact variable is required for our datadog configuration to work with tracing / APM
83+
- name: DD_AGENT_HOST
84+
value: "{{- if eq .Values.datadog.agentHost "127.0.0.1"}}$(NODE_IP){{- else}}{{ .Values.datadog.agentHost }}{{- end}}"
85+
86+
- name: DD_RUNTIME_METRICS_ENABLED
87+
value: "true"
88+
89+
- name: DD_SERVICE
90+
value: "opserver"
91+
92+
- name: KESTREL__ENDPOINTS__HTTP__URL
93+
value: "http://0.0.0.0:{{ .Values.kestrel.endPoints.http.containerPort }}/"
94+
95+
- name: TMPDIR #tell OS to use our read-write volume mount as its temp directory
96+
value: "/mnt/tmp"
97+
98+
- name: SQL_EXCEPTIONAL_SERVERNAME
99+
valueFrom:
100+
secretKeyRef:
101+
name: {{ .Values.sqlExternalSecret.targetName }}
102+
key: exceptionalServername
103+
- name: SQL_USERNAME
104+
valueFrom:
105+
secretKeyRef:
106+
name: {{ .Values.sqlExternalSecret.targetName }}
107+
key: exceptionalUsername
108+
- name: SQL_PASSWORD
109+
valueFrom:
110+
secretKeyRef:
111+
name: {{ .Values.sqlExternalSecret.targetName }}
112+
key: exceptionalPassword
113+
114+
{{- if hasKey .Values.opserverSettings "sql" }}
115+
- name: Modules__Sql__defaultConnectionString
116+
value: "Server=$(SQL_EXCEPTIONAL_SERVERNAME);Database=Local.Exceptions;User ID=$(SQL_USERNAME);Password=$(SQL_PASSWORD);"
117+
{{- range $i, $instance := .Values.opserverSettings.sql }}
118+
- name: Modules__Sql__instances__{{ $i }}__name
119+
value: "{{ $instance.name }}"
120+
{{- end }}
121+
{{- end }}
122+
123+
{{- if hasKey .Values.opserverSettings "exceptions" }}
124+
{{- range $i, $instance := .Values.opserverSettings.exceptions }}
125+
- name: Modules__Exceptions__stores__{{ $i }}__connectionString
126+
value: "Server={{ $instance.serverName}};Database={{ $instance.database}};User ID=$(SQL_USERNAME);Password=$(SQL_PASSWORD);"
127+
{{- end }}
128+
{{- end }}
129+
130+
topologySpreadConstraints:
131+
- maxSkew: 1
132+
topologyKey: kubernetes.io/hostname
133+
whenUnsatisfiable: ScheduleAnyway
134+
labelSelector:
135+
matchLabels:
136+
service: {{ .Release.Name }}
137+
matchLabelKeys:
138+
- pod-template-hash
139+
140+
{{- if and (hasKey .Values "nodeScheduling") (hasKey .Values.nodeScheduling "nodeSelectorLabel")}}
141+
nodeSelector:
142+
{{- range .Values.nodeScheduling.nodeSelectorLabel }}
143+
{{ .name }}: {{ .value | quote }}
144+
{{- end }}
145+
{{- end }}
146+
147+
{{- if and (hasKey .Values "nodeScheduling") (hasKey .Values.nodeScheduling "tolerations")}}
148+
tolerations:
149+
{{- range .Values.nodeScheduling.tolerations }}
150+
- key: {{ .key }}
151+
operator: {{ .operator }}
152+
value: {{ .value | quote }}
153+
effect: {{ .effect }}
154+
{{- end }}
155+
{{- end }}
156+
157+
restartPolicy: Always
158+
imagePullSecrets:
159+
- name: "{{ .Values.image.pullSecretName }}"
160+
volumes:
161+
- name: data-volume
162+
emptyDir: {}
163+
- name: log-volume
164+
emptyDir: {}
165+
volumes:
166+
- name: writable-tmp
167+
emptyDir: {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{{ if .Values.secretStore.fake }}
2+
apiVersion: external-secrets.io/v1beta1
3+
kind: ClusterSecretStore
4+
metadata:
5+
name: fakeopserversecretstore
6+
annotations:
7+
"helm.sh/hook": pre-install,pre-upgrade
8+
"helm.sh/hook-weight": "-5"
9+
spec:
10+
provider:
11+
fake:
12+
data:
13+
- key: "ExceptionsSqlServerName"
14+
value: "host.docker.internal"
15+
- key: "db-opserver-User"
16+
value: "opserver"
17+
- key: "db-opserver-Password"
18+
value: "opserver"
19+
{{ end }}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{{- if .Values.ingress.enabled }}
2+
apiVersion: networking.k8s.io/v1
3+
kind: Ingress
4+
metadata:
5+
name: {{ .Release.Name }}
6+
namespace: {{ .Release.Namespace }}
7+
annotations:
8+
cert-manager.io/cluster-issuer: {{ .Values.ingress.certIssuer }}
9+
spec:
10+
ingressClassName: {{ .Values.ingress.className }}
11+
{{- if .Values.ingress.createTlsCert }}
12+
tls:
13+
- hosts:
14+
- {{ .Values.ingress.host }}
15+
secretName: {{ .Values.ingress.secretName }}
16+
{{- end}}
17+
rules:
18+
- host: {{ .Values.ingress.host }}
19+
http:
20+
paths:
21+
- path: /
22+
pathType: ImplementationSpecific
23+
backend:
24+
service:
25+
name: {{ .Release.Name }}
26+
port:
27+
number: {{ .Values.kestrel.endPoints.http.containerPort }}
28+
{{- end}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apiVersion: v1
2+
kind: ServiceAccount
3+
metadata:
4+
name: {{ .Release.Name }}
5+
namespace: {{ .Release.Namespace }}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
namespace: {{ .Release.Namespace }}
5+
name: {{ .Release.Name }}
6+
spec:
7+
selector:
8+
service: {{ .Release.Name }}
9+
ports:
10+
- name: "80"
11+
port: 80
12+
targetPort: {{ .Values.kestrel.endPoints.http.containerPort }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: external-secrets.io/v1beta1
2+
kind: ExternalSecret
3+
metadata:
4+
name: {{ .Values.sqlExternalSecret.name }}
5+
spec:
6+
refreshInterval: {{ .Values.sqlExternalSecret.refreshInterval }}
7+
secretStoreRef:
8+
name: {{ .Values.sqlExternalSecret.storeRefName }}
9+
kind: ClusterSecretStore
10+
target:
11+
name: {{ .Values.sqlExternalSecret.targetName }}
12+
data:
13+
- secretKey: exceptionalServername
14+
remoteRef:
15+
key: {{ .Values.sqlExternalSecret.remoteRefs.exceptionalServerName }}
16+
- secretKey: exceptionalUsername
17+
remoteRef:
18+
key: {{ .Values.sqlExternalSecret.remoteRefs.exceptionalUsername }}
19+
- secretKey: exceptionalPassword
20+
remoteRef:
21+
key: {{ .Values.sqlExternalSecret.remoteRefs.exceptionalPassword }}

charts/opserver/values.yaml

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
appName: "opserver"
2+
replicaCount: 1
3+
4+
tier: "Local"
5+
product: "public" # used for datadog metrics and logs
6+
aspnetcoreEnvironment: "Local"
7+
8+
requests:
9+
cpu: "1m"
10+
memory: "1M"
11+
12+
limits:
13+
memory: "1Gi"
14+
15+
exceptional:
16+
store:
17+
type: "Memory"
18+
connectionString: ""
19+
20+
datadog:
21+
agentHost: ""
22+
agentPort: "0"
23+
24+
secretStore:
25+
fake: true
26+
27+
images:
28+
containerRegistry: "local.software"
29+
opserver:
30+
name: "stackeng/opserver/opserver"
31+
tag: "latest"
32+
33+
image:
34+
pullPolicy: IfNotPresent
35+
pullSecretName: cloudsmith-cr-prod
36+
37+
adminRolebindingGroupId: "not set"
38+
39+
kestrel:
40+
endPoints:
41+
http:
42+
url: "http://0.0.0.0:8080/"
43+
containerPort: 8080
44+
45+
ingress:
46+
certIssuer: "letsencrypt-staging"
47+
className: "nginx-external"
48+
host: "opserver.local"
49+
secretName: "opserver-secret"
50+
enabled: true
51+
createTlsCert: false
52+
53+
db:
54+
ExceptionalDbName: Local.Exceptions
55+
56+
sqlExternalSecret:
57+
name: opserver-sqldb-external-secret
58+
refreshInterval: 5m
59+
storeRefName: fakeopserversecretstore
60+
targetName: sql-secret
61+
remoteRefs:
62+
exceptionalServerName: ExceptionsSqlServerName
63+
exceptionalUsername: db-opserver-User
64+
exceptionalPassword: db-opserver-Password
65+
66+
nodeScheduling: {}

0 commit comments

Comments
 (0)