diff --git a/helm-overrides/gke-toolshed-prd-usc1/argocd-admin-prd/custom-values.yaml b/helm-overrides/gke-toolshed-prd-usc1/argocd-admin-prd/custom-values.yaml index f4f1ef2..4bf936b 100644 --- a/helm-overrides/gke-toolshed-prd-usc1/argocd-admin-prd/custom-values.yaml +++ b/helm-overrides/gke-toolshed-prd-usc1/argocd-admin-prd/custom-values.yaml @@ -81,21 +81,23 @@ argo-cd: ingress: enabled: true ingressClassName: contour - hostname: "argocd.35.238.248.203.nip.io" - # The chart supports additional hostnames natively, so the new domain - # is served here rather than from a second Ingress object. - extraHosts: - - name: "argocd.infra.deployshed.com" - path: / - # No TLS yet, deliberately. This chart's ingress.tls is a boolean, not - # a host list: turning it on requests ONE certificate covering - # `hostname` plus every extraHost, and Let's Encrypt cannot issue for - # nip.io — so the request would fail and neither name would be served - # over TLS. There is no extraTls to scope it more narrowly. + hostname: "argocd.infra.deployshed.com" + # TLS via extraTls rather than the `tls: true` boolean, deliberately. # - # This one gets its certificate when nip.io is retired and `hostname` - # itself becomes the deployshed.com name. Until then ArgoCD is HTTP - # only, as it already was. + # The boolean hardcodes `secretName: argocd-server-tls` (see the + # chart's argocd-server/ingress.yaml). This deployment already holds a + # valid, issued certificate for this exact hostname in + # argocd-deployshed-tls, created by the standalone Ingress that served + # the real domain while nip.io was still on `hostname`. Flipping the + # boolean would ignore that and request a second certificate for the + # same name — a needless issuance and a gap while it is obtained. + # + # extraTls takes an explicit secretName, so the existing certificate is + # adopted as-is and the standalone Ingress can simply be deleted. + extraTls: + - hosts: + - argocd.infra.deployshed.com + secretName: argocd-deployshed-tls resources: requests: cpu: 50m @@ -129,7 +131,10 @@ argo-cd: params: server.insecure: true cm: - url: "http://argocd.35.238.248.203.nip.io" + # https now that the only hostname served carries a real certificate. + # This is what ArgoCD builds its own links from, so leaving it http + # would hand out plain-HTTP URLs for a TLS-only deployment. + url: "https://argocd.infra.deployshed.com" timeout.reconciliation: 3m timeout.reconciliation.jitter: 60s # No Ingress health override, unlike the homelab: there Contour sat diff --git a/helm-overrides/gke-toolshed-prd-usc1/contour/custom-values.yaml b/helm-overrides/gke-toolshed-prd-usc1/contour/custom-values.yaml index a215b64..7607edb 100644 --- a/helm-overrides/gke-toolshed-prd-usc1/contour/custom-values.yaml +++ b/helm-overrides/gke-toolshed-prd-usc1/contour/custom-values.yaml @@ -35,10 +35,16 @@ contour: type: LoadBalancer # The reserved address from Terraform (module.network's - # google_compute_address). Every hostname in this deployment is - # .35.238.248.203.nip.io, so this pin is what makes DNS work at - # all — an unpinned Service takes a fresh ephemeral IP and every - # hostname points at nothing. + # google_compute_address). Every hostname in this deployment — the + # deployshed.com records, including the two wildcards — resolves here, + # so this pin is what makes DNS work at all: an unpinned Service takes + # a fresh ephemeral IP and every hostname points at nothing. + # + # More load-bearing now, not less, than when hostnames were + # .35.238.248.203.nip.io. Those encoded the address, so a changed + # IP produced names that were merely wrong. Real DNS records point here + # until somebody edits them in Cloudflare, so a changed IP is an + # outage across every hostname at once. # # spec.loadBalancerIP is deprecated upstream (Kubernetes 1.24), and # GKE's replacement is the annotation diff --git a/helm-overrides/gke-toolshed-prd-usc1/gitea/custom-values.yaml b/helm-overrides/gke-toolshed-prd-usc1/gitea/custom-values.yaml index eac2d81..42b2d31 100644 --- a/helm-overrides/gke-toolshed-prd-usc1/gitea/custom-values.yaml +++ b/helm-overrides/gke-toolshed-prd-usc1/gitea/custom-values.yaml @@ -43,7 +43,7 @@ gitea: actions: ENABLED: true server: - ROOT_URL: http://gitea.35.238.248.203.nip.io/ + ROOT_URL: https://gitea.infra.deployshed.com/ service: # The homelab sat on a LAN; this Gitea is on a public IP. Open # registration would let anyone on the internet create an account. @@ -69,7 +69,7 @@ gitea: # The proper fix is a configurable webhook base URL in toolshed # pointing at toolshed-api.toolshed.svc.cluster.local:8080, after # which this entry should be removed. - ALLOWED_HOST_LIST: private,toolshed.35.238.248.203.nip.io + ALLOWED_HOST_LIST: private,console.deployshed.com admin: username: gitadmin # Created by hand with kubectl at bootstrap, because Vault and ESO @@ -82,22 +82,20 @@ gitea: # Contour does not exist yet at bootstrap — the Ingress just sits unused # until ArgoCD installs it. # - # Two hosts while the deployment moves onto its own domain. The nip.io one - # stays until everything that references it has been repointed — ROOT_URL - # below, and any git remote anyone has configured. + # One host. The nip.io name was served alongside this one while the + # deployment moved onto its own domain, and came out once everything + # referencing it had been repointed: ROOT_URL above, the webhook allow-list + # above that, and any git remote anyone had configured. ingress: enabled: true className: contour annotations: - # Issues the certificate named in tls below. Only the real domain is - # listed there: Let's Encrypt cannot issue for nip.io, and asking for - # one certificate spanning both names returns nothing for either. + # Issues the certificate named in tls below. This could only ever cover + # the real domain: Let's Encrypt cannot issue for nip.io, so while both + # names were served, asking for one certificate spanning them returned + # nothing for either. cert-manager.io/cluster-issuer: letsencrypt-prod hosts: - - host: gitea.35.238.248.203.nip.io - paths: - - path: / - pathType: Prefix - host: gitea.infra.deployshed.com paths: - path: / diff --git a/helm-overrides/gke-toolshed-prd-usc1/grafana/custom-values.yaml b/helm-overrides/gke-toolshed-prd-usc1/grafana/custom-values.yaml index b5aacb1..c917a3d 100644 --- a/helm-overrides/gke-toolshed-prd-usc1/grafana/custom-values.yaml +++ b/helm-overrides/gke-toolshed-prd-usc1/grafana/custom-values.yaml @@ -268,13 +268,14 @@ grafana: enabled: true ingressClassName: contour annotations: - # Only the real domain appears in tls below — Let's Encrypt cannot - # issue for nip.io, and one certificate spanning both would fail - # outright rather than covering the half it can serve. + # The real domain is now the only host, so this covers everything + # served. While nip.io was alongside it, only the real domain could + # appear in tls below — Let's Encrypt cannot issue for nip.io, and one + # certificate spanning both would have failed outright rather than + # covering the half it could serve. cert-manager.io/cluster-issuer: letsencrypt-prod path: / hosts: - - grafana.35.238.248.203.nip.io - grafana.infra.deployshed.com tls: - secretName: grafana-tls diff --git a/helm-overrides/gke-toolshed-prd-usc1/harbor/custom-values.yaml b/helm-overrides/gke-toolshed-prd-usc1/harbor/custom-values.yaml index 6f452c5..eca94bb 100644 --- a/helm-overrides/gke-toolshed-prd-usc1/harbor/custom-values.yaml +++ b/helm-overrides/gke-toolshed-prd-usc1/harbor/custom-values.yaml @@ -6,41 +6,69 @@ harbor: # The homelab runs Harbor on plain HTTP and works around containerd's # refusal to pull from an insecure registry by hand-editing # /etc/containerd/certs.d//hosts.toml on the node. GKE nodes are - # managed and replaced, so that edit cannot survive. Instead the node pool - # is told, at creation, to trust a private CA for exactly this hostname, - # fetching it from Secret Manager (see toolshed-gke-infra's gke-cluster - # module). cert-manager signs Harbor's certificate from that same CA. + # managed and replaced, so that edit cannot survive. # - # Let's Encrypt is not an option: nip.io is not on the public suffix list, - # so every *.nip.io certificate on the internet shares one rate limit. - # A private CA is fine for image pulls, which is what matters, but - # browsers will warn on the Harbor UI. That is expected, not a fault. + # That used to mean a private CA: the registry was a nip.io name, Let's + # Encrypt cannot issue for one (not on the public suffix list, and every + # *.nip.io certificate shares a single rate limit), so Terraform generated + # a CA, the node pool was told at creation to trust it for exactly that + # hostname, and cert-manager signed Harbor from it. It worked for pulls, + # which is what mattered, but every browser warned on the Harbor UI and + # every docker client that was not a node needed the CA mounted by hand. + # + # Owning a domain removes all of it. harbor.infra.deployshed.com takes an + # ordinary Let's Encrypt certificate that everything already trusts — the + # nodes, dockerd in a build pod, a laptop, a browser. What retires with it: + # registry-ca-clusterissuer.yaml, registry-ca-configmap.yaml, the CA mount + # in every dind pod, and eventually the node pool's own + # private_registry_access_config block in Terraform. + # + # The nip.io name is still served, by a standalone Ingress alongside this + # one, and still signed by the private CA. It has to be: apps deployed + # before the move recorded their image as harbor.35.238.248.203.nip.io/... + # in toolshed's database, and that reference only changes when each app is + # rebuilt. Retiring the old name before then breaks their next image pull. expose: type: ingress tls: enabled: true # secret, not the chart's "auto": auto generates its own self-signed - # certificate, which the nodes have no reason to trust. This one is - # signed by the CA they were told to trust. + # certificate, which nothing has any reason to trust. certSource: secret secret: - secretName: harbor-tls + secretName: harbor-deployshed-tls ingress: hosts: - core: "harbor.35.238.248.203.nip.io" + core: "harbor.infra.deployshed.com" className: contour annotations: # cert-manager's ingress-shim watches for this and creates the # Certificate itself, writing the result into the secret named # above. Nothing here ever touches a Certificate resource directly. - # The issuer is defined in devops-infra-argo-config-gcp's - # extra-manifests/registry-ca-clusterissuer.yaml. - cert-manager.io/cluster-issuer: registry-ca-issuer + cert-manager.io/cluster-issuer: letsencrypt-prod + + # The update strategy for the two deployments with persistent volumes, + # jobservice and registry. Recreate, not the chart's default RollingUpdate, + # because their volumes are standard-rwo — ReadWriteOnce — and a rolling + # update starts the replacement pod before the old one releases the disk. + # The new pod then waits on "Multi-Attach error for volume ... already used + # by pod" forever, and the rollout never converges: this cluster sat in + # exactly that state, old pods serving while new ones hung in + # ContainerCreating. The chart's own comment on this value says to set it + # this way when RWM volumes are unavailable. + # + # The cost is honest: Harbor is briefly down during an upgrade, because the + # old pod must stop before the new one starts. That beats an update that + # cannot complete at all. + updateStrategy: + type: Recreate # https, matching the ingress above. Harbor hands this URL to docker # clients in its own API responses, so a mismatch here breaks pushes in - # ways that look like registry errors rather than configuration. - externalURL: "https://harbor.35.238.248.203.nip.io" + # ways that look like registry errors rather than configuration — and it is + # what the "docker login / docker push" commands shown in Harbor's own UI + # are built from, which is where a stale value is noticed first. + externalURL: "https://harbor.infra.deployshed.com" # From Vault through External Secrets — see # secretstores/harbor-admin-credentials.yaml and Vault path diff --git a/helm-overrides/gke-toolshed-prd-usc1/jenkins/custom-values.yaml b/helm-overrides/gke-toolshed-prd-usc1/jenkins/custom-values.yaml index 2514572..91e5bfc 100644 --- a/helm-overrides/gke-toolshed-prd-usc1/jenkins/custom-values.yaml +++ b/helm-overrides/gke-toolshed-prd-usc1/jenkins/custom-values.yaml @@ -55,27 +55,23 @@ jenkins: userKey: jenkins-admin-user passwordKey: jenkins-admin-password - ingress: - enabled: true - hostName: "jenkins.35.238.248.203.nip.io" - ingressClassName: contour + # One hostname, on the primary ingress, with its certificate. + # # This chart's primary ingress supports exactly one hostName — no - # extraHosts like argo-cd. secondaryingress renders a whole second - # Ingress object at the same backend, which is the supported way to get - # a second hostname here. + # extraHosts like argo-cd — so while nip.io was also served, the real + # domain lived in a whole second Ingress object (secondaryingress). That + # was the only way to keep the certificate clean, since a certificate + # covering both names is impossible: Let's Encrypt cannot issue for + # nip.io. With nip.io gone there is one name, so the second object is + # gone with it and the certificate moves onto the primary. # - # paths must be set explicitly: the template renders zero routes if left - # at the chart's own default of [], unlike the primary ingress, and the - # hostname would then answer nothing at all. - # - # Being a separate Ingress object is what makes the certificate clean — - # it covers this hostname alone, with no nip.io name to drag in. - secondaryingress: + # controller.ingress.tls is a LIST here, not a boolean, taking an + # explicit secretName — so jenkins-tls, already issued for this exact + # hostname by the secondary ingress, is adopted rather than reissued. + ingress: enabled: true hostName: "jenkins.infra.deployshed.com" ingressClassName: contour - paths: - - / annotations: cert-manager.io/cluster-issuer: letsencrypt-prod tls: diff --git a/helm-overrides/gke-toolshed-prd-usc1/vault/custom-values.yaml b/helm-overrides/gke-toolshed-prd-usc1/vault/custom-values.yaml index 23abb60..e17b0bf 100644 --- a/helm-overrides/gke-toolshed-prd-usc1/vault/custom-values.yaml +++ b/helm-overrides/gke-toolshed-prd-usc1/vault/custom-values.yaml @@ -84,11 +84,10 @@ vault: enabled: true ingressClassName: contour annotations: - # Certificate for the real domain only; nip.io cannot have one. + # Certificate for the real domain, which is now the only one served. + # nip.io could never have had one. cert-manager.io/cluster-issuer: letsencrypt-prod hosts: - - host: "vault.35.238.248.203.nip.io" - paths: [] - host: "vault.infra.deployshed.com" paths: [] tls: diff --git a/helm-overrides/gke-toolshed-prd-usc1/victoria-metrics-single/custom-values.yaml b/helm-overrides/gke-toolshed-prd-usc1/victoria-metrics-single/custom-values.yaml index 7b389d9..dcb0a9e 100644 --- a/helm-overrides/gke-toolshed-prd-usc1/victoria-metrics-single/custom-values.yaml +++ b/helm-overrides/gke-toolshed-prd-usc1/victoria-metrics-single/custom-values.yaml @@ -56,12 +56,10 @@ victoria-metrics-single: enabled: true ingressClassName: contour annotations: - # Certificate for the real domain only; nip.io cannot have one. + # Certificate for the real domain, now the only one served. nip.io + # could never have had one. cert-manager.io/cluster-issuer: letsencrypt-prod hosts: - - name: vm.35.238.248.203.nip.io - path: ["/"] - port: http - name: vm.infra.deployshed.com path: ["/"] port: http