blob: 0e4ebb1c2b372f06d72e96ad0bcbf7df7539a89a [file] [log] [blame]
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +02001# Deploy a Docker Registry in a cluster.
2
3# This needs an oauth2 secret provisioned, create with:
4# kubectl -n registry create secret generic auth --from-literal=oauth2_secret=...
5# kubectl get secrets rook-ceph-object-user-<ceph-pool>-object-registry -n <ceph-namespace> -o yaml --export | kubectl replace -f - -n registry
6
7local kube = import "../../../kube/kube.libsonnet";
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +02008
9{
10 Environment: {
11 local env = self,
12 local cfg = env.cfg,
13 cfg:: {
14 namespace: "registry",
15 domain: error "domain must be set",
16 storageClassName: error "storageClassName must be set",
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +020017 objectStoreName: error "objectStoreName must be set",
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020018 },
19
20 metadata(component):: {
21 namespace: cfg.namespace,
22 labels: {
23 "app.kubernetes.io/name": "registry",
24 "app.kubernetes.io/managed-by": "kubecfg",
25 "app.kubernetes.io/component": component,
26 },
27 },
28
29 namespace: kube.Namespace(cfg.namespace),
30
Sergiusz Bazanskie31d64f2019-10-02 20:59:26 +020031 registryIssuer: kube.Issuer("registry-issuer") {
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020032 metadata+: env.metadata("registry-issuer"),
33 spec: {
34 selfSigned: {},
35 },
36 },
Sergiusz Bazanskie31d64f2019-10-02 20:59:26 +020037 authCertificate: kube.Certificate("auth") {
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020038 metadata+: env.metadata("auth"),
39 spec: {
40 secretName: "auth-internal",
41 duration: "43800h0m0s", // 5 years
42 issuerRef: {
43 name: env.registryIssuer.metadata.name,
44 },
45 commonName: "auth.registry",
46 },
47 },
Sergiusz Bazanskie31d64f2019-10-02 20:59:26 +020048 registryCertificate: kube.Certificate("registry") {
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020049 metadata+: env.metadata("registry"),
50 spec: {
51 secretName: "registry-internal",
52 duration: "43800h0m0s", // 5 years
53 issuerRef: {
54 name: env.registryIssuer.metadata.name,
55 },
56 commonName: "registry.registry",
57 },
58 },
59
60 registryConfig: kube.ConfigMap("registry-config") {
61 metadata+: env.metadata("registry-config"),
62 data: {
63 "config.yml": std.manifestYamlDoc({
64 version: "0.1",
65 log: {
Sergiusz Bazanski5f3a5e02019-09-25 02:51:51 +020066 level: "debug",
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020067 fields: {
68 service: "registry",
69 },
70 },
71 storage: {
72 cache: {
73 blobdescriptor: "inmemory",
74 },
75 s3: {
Serge Bazanski3d294842020-08-04 01:34:07 +020076 regionendpoint: "https://object.ceph-waw3.hswaw.net",
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020077 bucket: "registry",
Serge Bazanski3d294842020-08-04 01:34:07 +020078 region: "waw-hdd-redunant-3-object:default-placement",
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020079 },
80 },
81 http: {
82 addr: ":5000",
83 headers: {
84 "X-Content-Type-Options": ["nosniff"],
85 },
86 tls: {
87 certificate: "/certs/tls.crt",
88 key: "/certs/tls.key",
89 },
90 debug: {
91 addr: "localhost:5001",
92 },
93 },
94 health: {
95 storagedriver: {
96 enabled: true,
97 interval: "10s",
98 threshold: 3,
99 },
100 },
101 auth: {
102 token: {
103 realm: "https://%s/auth" % [cfg.domain],
104 service: "my.docker.registry",
105 issuer: "%s auth server" % [cfg.domain],
106 rootcertbundle: "/authcerts/tls.crt",
107 },
108 },
109 }),
110 },
111 },
112
Serge Bazanski3d294842020-08-04 01:34:07 +0200113 authVolumeClaim: kube.PersistentVolumeClaim("auth-token-storage-3") {
114 metadata+: env.metadata("auth-token-storage-3"),
radex36964dc2023-11-24 11:19:46 +0100115 storage:: "1Gi",
116 storageClass:: cfg.storageClassName,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200117 },
118
119 authConfig: kube.ConfigMap("auth-config") {
120 metadata+: env.metadata("auth-config"),
121 data: {
122 "auth_config.yml": std.manifestYamlDoc({
123 server: {
124 addr: ":5001",
125 certificate: "/certs/tls.crt",
126 key: "/certs/tls.key",
127 },
128 token: {
129 issuer: "%s auth server" % [cfg.domain],
130 expiration: 900,
131 },
132 oauth2: {
133 client_id: "registry",
134 client_secret_file: "/secrets/oauth2_secret",
135 authorize_url: "https://sso.hackerspace.pl/oauth/authorize",
136 access_token_url: "https://sso.hackerspace.pl/oauth/token",
137 profile_url: "https://sso.hackerspace.pl/api/1/profile",
138 redirect_url: "https://registry.k0.hswaw.net/oauth2",
139 username_key: "username",
140 token_db: "/data/oauth2_tokens.ldb",
141 registry_url: "https://registry.k0.hswaw.net",
142 },
143 users: {
144 [""]: {}, // '' user are anonymous users.
145 },
146 local data = self,
147 pushers:: [
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +0200148 { who: ["q3k", "informatic"], what: "vms/*" },
149 { who: ["q3k", "informatic"], what: "app/*" },
150 { who: ["q3k", "informatic"], what: "go/svc/*" },
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200151 { who: ["q3k"], what: "bgpwtf/*" },
152 { who: ["q3k"], what: "devtools/*" },
Sergiusz Bazanski0581bbf2020-05-11 03:21:32 +0200153 { who: ["q3k"], what: "games/factorio/*" },
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +0200154 { who: ["q3k", "informatic"], what: "cluster/*" },
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200155 ],
156 acl: [
157 {
Piotr Dobrowolski10384cd2023-06-20 00:42:15 +0200158 match: {
159 account: "/(%s)/" % std.join("|", p.who),
160 name: p.what,
161 },
162 actions: ["*"],
163 comment: "%s can push to %s" % [std.join(", ", p.who), p.what],
164 }
165 for p in data.pushers
166 ] + [
167 {
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200168 match: {account: "/.+/", name: "${account}/*"},
169 actions: ["*"],
170 comment: "Logged in users have full access to images that are in their 'namespace'",
171 },
172 {
173 match: {account: "/.+/", type: "registry", name: "catalog"},
174 actions: ["*"],
175 comment: "Logged in users can query the catalog.",
176 },
177 {
Piotr Dobrowolski0697e012020-07-02 18:32:24 +0200178 match: {account: "/.*/"},
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200179 actions: ["pull"],
180 comment: "Anyone can pull all images.",
181 },
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200182 ],
183 }),
184 }
185 },
186
187 authDeployment: kube.Deployment("auth") {
188 metadata+: env.metadata("auth"),
189 spec+: {
190 replicas: 1,
191 template+: {
192 spec+: {
193 volumes_: {
194 data: kube.PersistentVolumeClaimVolume(env.authVolumeClaim),
195 config: kube.ConfigMapVolume(env.authConfig),
196 certs: {
197 secret: { secretName: env.authCertificate.spec.secretName },
198 },
199 secrets: {
200 secret: { secretName: "auth" },
201 },
202 },
203 containers_: {
204 auth: kube.Container("auth") {
205 image: "informatic/docker_auth:2019040307",
206 volumeMounts_: {
207 config: { mountPath: "/config" },
208 certs: { mountPath: "/certs" },
209 secrets: { mountPath: "/secrets" },
210 data: { mountPath: "/data" },
211 },
212 },
213 },
214 },
215 },
216 },
217 },
218 authService: kube.Service("auth") {
219 metadata+: env.metadata("auth"),
radex8b8f3872023-11-24 11:09:46 +0100220 target:: env.authDeployment,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200221 spec+: {
222 type: "ClusterIP",
223 ports: [
224 { name: "auth", port: 5001, targetPort: 5001, protocol: "TCP" },
225 ],
226 }
227 },
228 registryDeployment: kube.Deployment("docker-registry") {
229 metadata+: env.metadata("docker-registry"),
230 spec+: {
231 replicas: 1,
232 template+: {
233 spec+: {
234 volumes_: {
235 config: kube.ConfigMapVolume(env.registryConfig),
236 certs: {
237 secret: { secretName: env.registryCertificate.spec.secretName },
238 },
239 authcerts: {
240 secret: { secretName: env.authCertificate.spec.secretName },
241 },
242 },
243 containers_: {
244 registry: kube.Container("docker-registry") {
Sergiusz Bazanski5f3a5e02019-09-25 02:51:51 +0200245 image: "registry:2.7.1",
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200246 args: ["/config/config.yml"],
247 volumeMounts_: {
248 config: { mountPath: "/config" },
249 certs: { mountPath: "/certs" },
250 authcerts: { mountPath: "/authcerts" },
251 },
252 env_: {
253 REGISTRY_STORAGE_S3_ACCESSKEY: { secretKeyRef: {
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200254 name: "rook-ceph-object-user-%(objectStorageName)s-registry" % {objectStorageName: cfg.objectStorageName},
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200255 key: "AccessKey"
256 }},
257 REGISTRY_STORAGE_S3_SECRETKEY: { secretKeyRef: {
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200258 name: "rook-ceph-object-user-%(objectStorageName)s-registry" % {objectStorageName: cfg.objectStorageName},
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200259 key: "SecretKey",
260 }},
261 },
262 },
263 },
264 },
265 },
266 },
267 },
268 registryService: kube.Service("docker-registry") {
269 metadata+: env.metadata("docker-registry"),
radex8b8f3872023-11-24 11:09:46 +0100270 target:: env.registryDeployment,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200271 spec+: {
272 type: "ClusterIP",
273 ports: [
274 { name: "registry", port: 5000, targetPort: 5000, protocol: "TCP" },
275 ],
276 }
277 },
278 registryIngress: kube.Ingress("registry") {
279 metadata+: env.metadata("registry") {
280 annotations+: {
281 "kubernetes.io/tls-acme": "true",
Piotr Dobrowolski7e841062023-04-23 11:36:15 +0200282 "cert-manager.io/cluster-issuer": "letsencrypt-prod",
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200283 "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
284 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
285 },
286 },
287 spec+: {
288 tls: [
289 {
290 hosts: [cfg.domain],
291 secretName: "registry-tls",
292 },
293 ],
294 rules: [
295 {
296 host: cfg.domain,
297 http: {
298 paths: [
299 { path: "/auth", backend: env.authService.name_port },
300 { path: "/", backend: env.authService.name_port },
301 { path: "/v2/", backend: env.registryService.name_port },
302 ]
303 },
304 }
305 ],
306 },
307 },
308
Sergiusz Bazanskie186c872020-02-21 12:57:02 +0100309 registryStorageUser: kube.CephObjectStoreUser("registry") {
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200310 metadata+: {
Serge Bazanski3d294842020-08-04 01:34:07 +0200311 namespace: "ceph-waw3",
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200312 },
313 spec: {
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200314 store: cfg.objectStorageName,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200315 displayName: "docker-registry user",
316 },
317 },
318 }
319}