2024-03-12 23:53:26 +00:00
<!DOCTYPE html>
< html lang = "en" >
< head > < title > Hugo on Kubernetes & NGINX – estradiol.cloud< / title >
< meta name = "description" content = "> [ the regrown limb can be monstrous , duplicated , potent . We have all been injured , profoundly . ] ( https: / / doi . org / 10 . 5749 / minnesota / 9780816650477 . 003 . 0001 )
----
2024-03-13 03:55:20 +00:00
Ь 887 | 2
2024-03-12 23:53:26 +00:00
">
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< meta charset = "UTF-8" / >
< link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity = "sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin = "anonymous" referrerpolicy = "no-referrer" / >
< link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/academicons/1.9.4/css/academicons.min.css" integrity = "sha512-IW0nhlW5MgNydsXJO40En2EoCkTTjZhI3yuODrZIc8cQ4h1XcF53PsqDHa09NqnkXuIe0Oiyyj171BqZFwISBw==" crossorigin = "anonymous" referrerpolicy = "no-referrer" / >
< link rel = "stylesheet" href = "https://estradiol.cloud/css/palettes/material.css" >
< link rel = "stylesheet" href = "https://estradiol.cloud/css/risotto.css" >
< link rel = "stylesheet" href = "https://estradiol.cloud/css/custom.css" >
< link rel = "alternate" type = "application/rss+xml" title = "estradiol.cloud Feed" href = "index.xml" / >
< / head >
< body >
< div class = "page" >
< header class = "page__header" > < nav class = "page__nav main-nav" >
< ul >
< li class = "nomarker" > < h1 class = "page__logo" > < a href = "https://estradiol.cloud/" class = "page__logo-inner" > estradiol.cloud< / a > < / h1 > < / li >
< li class = "main-nav__item" > < a class = "nav-main-item active" href = "https://estradiol.cloud/posts/" title = "" > Posts< / a > < / li >
< / ul >
< / nav >
< / header >
< section class = "page__body" >
< header class = "content__header" >
< h1 > Hugo on Kubernetes & NGINX< / h1 >
< / header >
< div class = "content__body" >
< p > i decided to make a website. a static one. this one. with < a href = "https://gohugo.io" > Hugo< / a > . the
main reason i have for needing a website is as a vanity project, so i have some
stuff to host in a < a href = "https://kubernetes.io" > Kubernetes< / a > cluster i’ m running. the k8s cluster is
also a vanity project.< / p >
< p > because i don’ t like software, i wanted a way to deploy my site that doesn’ t
involve much of it. this post is about that.< / p >
< h2 id = "getting-started" > Getting Started< / h2 >
< p > i built my site by following the straight-forward
< em > < a href = "https://gohugo.io/getting-started" > Getting Started< / a > < / em > guide in the Hugo documentation.< / p >
< p > i did < code > hugo new site estradiol.cloud< / code > . and then < code > cd estradiol.cloud; git init< / code > .
and then i picked a ridiculous theme
< a href = "https://github.com/joeroe/risotto" > “ inspired by terminal ricing aesthetics” < / a > , installing it like < code > git submodule add https://github.com/joeroe/risotto.git themes/risotto; echo " theme = 'risotto'" > > hugo.toml< / code > .< sup id = "fnref:1" > < a href = "#fn:1" class = "footnote-ref" role = "doc-noteref" > 1< / a > < / sup > < / p >
< p > at this point, my website is basically finished (i also changed the title in
< code > hugo.toml< / code > ). i probably won’ t be putting anything on it, so there’ s no point
fiddling with other details.< / p >
< p > about deployment, the Hugo guide’ s < em > < a href = "https://gohugo.io/getting-started/usage/#deploy-your-site" > Basic Usage< / a > < / em > page has this
to offer:< / p >
< blockquote >
< p > Most of our users deploy their sites using a CI/CD workflow, where a push< sup > 1< / sup >
to their GitHub or GitLab repository triggers a build and deployment. Popular
providers include AWS Amplify, CloudCannon, Cloudflare Pages, GitHub Pages,
GitLab Pages, and Netlify.< / p >
< ol >
< li > The Git repository contains the entire project directory, typically excluding the
public directory because the site is built < em > after< / em > the push.< / li >
< / ol >
< / blockquote >
< p > importantly, you can’ t make a post about deploying this way. < em > everyone< / em > deploys
this way. if < em > i< / em > deploy this way, this site will have no content.< / p >
< p > this approach also involves a build system somewhere that can run Hugo to
compile the code and assets and push them onto my host. i definitely
already need Hugo installed on my laptop if i’ m going to post anything.< sup id = "fnref:2" > < a href = "#fn:2" class = "footnote-ref" role = "doc-noteref" > 2< / a > < / sup >
so now i’ m running Hugo in two places. there’ s surely going to be other
complex nonsense like webhooks involved.< / p >
< p > < img src = "images/hugo-github-pages.svg" alt = "diagram: deploy w/ GitHub Pages & Actions" > < / p >
< hr >
< p > and hang on. let’ s look at this again:< / p >
< blockquote >
< ol >
< li > The Git repository contains the entire project directory, typically excluding the
public directory because the site is built < em > after< / em > the push.< / li >
< / ol >
< / blockquote >
< p > you’ re telling me i’ m going to build a nice static site and not check the
< em > actual content< / em > into version control? couldn’ t be me.< / p >
< h2 id = "getting-static" > Getting Static< / h2 >
< p > suppose i instead check my content in exactly as i intend to serve it?
then i could shell into my server box, pull the site, and < em > nifty-galifty!< / em > isn’ t
this the way it has < a href = "https://www.mikecurato.com/worm-loves-worm" > always been done< / a > ?< / p >
< p > my problem is that i don’ t have a server box. i have a < em > container orchestration
system< / em > . there are several upsides to this< sup id = "fnref:3" > < a href = "#fn:3" class = "footnote-ref" role = "doc-noteref" > 3< / a > < / sup > but it means that < em > somehow< / em > my
generated content needs to end up in a container. because < a href = "https://kubernetes.io/docs/concepts/workloads/pods/" > Pods< / a > are
ephemeral and i’ d like to run my site with horizontal scalability< sup id = "fnref:4" > < a href = "#fn:4" class = "footnote-ref" role = "doc-noteref" > 4< / a > < / sup > , i don’ t
want my container to retain runtime state across restarts or replicas.< / p >
< p > i < em > could< / em > run a little pipeline that builds a container image wrapping my
content and pushes it to a registry. when i deploy, the cluster pulls the
image, content and all. all ready to go. but now i’ ve got < em > software< / em > again:
build stages and webhooks and, to make matters worse, now i’ m hosting
and versioning container images.< / p >
< p > < img src = "images/hugo-container-build.svg" alt = "diagram: deploy w/ container build" > < / p >
< p > i don’ t want any of this. i just want to put some HTML and static assets behind a
web server.< / p >
< hr >
< p > instead, i’ d like to deploy a popular container image from a public registry
and deliver my content to it continuously.< / p >
< p > a minimal setup to achieve this might look like:< / p >
< ul >
< li > a < code > Pod< / code > with:
< ul >
< li > an < code > nginx< / code > container to serve the content;< / li >
< li > a < code > git-pull< / code > sidecar that loops, pulling the content;< / li >
< li > an < code > initContainer< / code > to do the initial checkout;< / li >
< li > an < code > emptyDir< / code > volume to share between the containers.< / li >
< / ul >
< / li >
< li > a < code > ConfigMap< / code > to store the nginx config.< / li >
< / ul >
< p > < img src = "images/hugo-minimal-pod-setup.svg" alt = "diagram: minimal pod/configmap setup" > < / p >
< p > when a new < code > Pod< / code > comes up, the < code > initContainer< / code > mounts the
< a href = "https://kubernetes.io/docs/concepts/storage/volumes/#emptydir" > < code > emptyDir< / code > < / a > at < code > /www< / code > and clones the repository into it. i use
< code > git sparse-checkout< / code > to avoid pulling repository contents i don’ t want to serve
out:< / p >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-bash" data-lang = "bash" > < span style = "display:flex;" > < span > < span style = "color:#75715e" > # git-clone command< / span >
< / span > < / span > < span style = "display:flex;" > < span > git clone https://code.estradiol.cloud/tamsin/estradiol.cloud.git --no-checkout --branch trunk /tmp/www;
< / span > < / span > < span style = "display:flex;" > < span > cd /tmp/www;
< / span > < / span > < span style = "display:flex;" > < span > git sparse-checkout init --cone;
< / span > < / span > < span style = "display:flex;" > < span > git sparse-checkout set public;
< / span > < / span > < span style = "display:flex;" > < span > git checkout;
< / span > < / span > < span style = "display:flex;" > < span > shopt -s dotglob
< / span > < / span > < span style = "display:flex;" > < span > mv /tmp/www/* /www
< / span > < / span > < / code > < / pre > < / div > < p > for the sidecar, i script up a < code > git pull< / code > loop:< / p >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-bash" data-lang = "bash" > < span style = "display:flex;" > < span > < span style = "color:#75715e" > # git-pull command< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#66d9ef" > while< / span > true; < span style = "color:#66d9ef" > do< / span >
< / span > < / span > < span style = "display:flex;" > < span > cd /www < span style = "color:#f92672" > & & < / span > git -c safe.directory< span style = "color:#f92672" > =< / span > /www pull origin trunk
< / span > < / span > < span style = "display:flex;" > < span > sleep < span style = "color:#ae81ff" > 60< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#66d9ef" > done< / span >
< / span > < / span > < / code > < / pre > < / div > < p > and i create a < a href = "https://kubernetes.io/docs/concepts/configuration/configmap/" > ConfigMap< / a > with a server block to configure
< code > nginx< / code > to use Hugo’ s < code > public/< / code > as root:< / p >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-txt" data-lang = "txt" > < span style = "display:flex;" > < span > # ConfigMap; data: default.conf
< / span > < / span > < span style = "display:flex;" > < span > server {
< / span > < / span > < span style = "display:flex;" > < span > listen 80;
< / span > < / span > < span style = "display:flex;" > < span > location / {
< / span > < / span > < span style = "display:flex;" > < span > root /www/public;
< / span > < / span > < span style = "display:flex;" > < span > index index.html;
< / span > < / span > < span style = "display:flex;" > < span > }
< / span > < / span > < span style = "display:flex;" > < span > }
< / span > < / span > < / code > < / pre > < / div > < p > the rest of this is pretty much boilerplate:< / p >
< p >
< details >
< summary > < code > kubectl apply -f https://estradiol.cloud/posts/hugo-on-k8s/site.yaml< / code > < / summary >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-yaml" data-lang = "yaml" > < span style = "display:flex;" > < span > < span style = "color:#75715e" > # estradiol-cloud.yaml< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > apiVersion< / span > : < span style = "color:#ae81ff" > v1< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > kind< / span > : < span style = "color:#ae81ff" > ConfigMap< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > metadata< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > labels< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/instance< / span > : < span style = "color:#ae81ff" > estradiol-cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx-server-block< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > data< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > default.conf< / span > : |-< span style = "color:#e6db74" >
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > server {
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > listen 80;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > location / {
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > root /www/public;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > index index.html;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > }
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > }< / span >
< / span > < / span > < span style = "display:flex;" > < span > ---
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > apiVersion< / span > : < span style = "color:#ae81ff" > v1< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > kind< / span > : < span style = "color:#ae81ff" > Pod< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > metadata< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > labels< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/instance< / span > : < span style = "color:#ae81ff" > estradiol-cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > spec< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > containers< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > image< / span > : < span style = "color:#ae81ff" > nginx:1.25.4< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > ports< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > containerPort< / span > : < span style = "color:#ae81ff" > 80< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > volumeMounts< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > mountPath< / span > : < span style = "color:#ae81ff" > /www< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > www< / span >
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > mountPath< / span > : < span style = "color:#ae81ff" > /etc/nginx/conf.d< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx-server-block< / span >
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > git-pull< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > image< / span > : < span style = "color:#ae81ff" > bitnami/git< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > command< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#ae81ff" > /bin/bash< / span >
< / span > < / span > < span style = "display:flex;" > < span > - -< span style = "color:#ae81ff" > ec< / span >
< / span > < / span > < span style = "display:flex;" > < span > - |< span style = "color:#e6db74" >
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > while true; do
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > cd /www & & git -c safe.directory=/www pull origin trunk
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > sleep 60
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > done< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > volumeMounts< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > mountPath< / span > : < span style = "color:#ae81ff" > /www< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > www< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > initContainers< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > git-clone< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > image< / span > : < span style = "color:#ae81ff" > bitnami/git< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > command< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#ae81ff" > /bin/bash< / span >
< / span > < / span > < span style = "display:flex;" > < span > - -< span style = "color:#ae81ff" > c< / span >
< / span > < / span > < span style = "display:flex;" > < span > - |< span style = "color:#e6db74" >
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > shopt -s dotglob
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > git clone https://code.estradiol.cloud/tamsin/estradiol.cloud.git --no-checkout --branch trunk /tmp/www;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > cd /tmp/www;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > git sparse-checkout init --cone;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > git sparse-checkout set public;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > git checkout;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > mv /tmp/www/* /www< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > volumeMounts< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > mountPath< / span > : < span style = "color:#ae81ff" > /www< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > www< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > volumes< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > www< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > emptyDir< / span > : {}
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx-server-block< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > configMap< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx-server-block< / span >
< / span > < / span > < / code > < / pre > < / div >
< / details >
< / p >
< hr >
< p > my Hugo workflow now looks like:< / p >
< ol >
< li > make changes to source;< / li >
< li > run < code > hugo --gc --minify< / code > ;< sup id = "fnref:5" > < a href = "#fn:5" class = "footnote-ref" role = "doc-noteref" > 5< / a > < / sup > < / li >
< li > < code > git< / code > commit & push.< / li >
< / ol >
< p > my < code > git pull< / code > control loop takes things over from here and i’ m on easy street.< / p >
< h2 id = "getting-web" > Getting Web< / h2 >
< p > this is going great! my < code > Pod< / code > is running. it’ s serving out my code. i get
Continuous Deployment™ for the low price of 11 lines < code > bash< / code > . i mean…
no one can actually browse to my website< sup id = "fnref:6" > < a href = "#fn:6" class = "footnote-ref" role = "doc-noteref" > 6< / a > < / sup > but that will be an easy fix,
right? yes. networking is always the easy part.< / p >
< p > first, i need a < a href = "https://kubernetes.io/docs/concepts/services-networking/service/" > < code > Service< / code > < / a > . this gives me a proxy to my several
replicas< sup id = "fnref:7" > < a href = "#fn:7" class = "footnote-ref" role = "doc-noteref" > 7< / a > < / sup > and in-cluster service discovery.< / p >
< p >
< details >
< summary > < code > kubectl apply -f https://estradiol.cloud/posts/hugo-on-k8s-nginx/service.yaml< / code > < / summary >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-yaml" data-lang = "yaml" > < span style = "display:flex;" > < span > < span style = "color:#75715e" > # service.yaml< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > apiVersion< / span > : < span style = "color:#ae81ff" > v1< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > kind< / span > : < span style = "color:#ae81ff" > Service< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > metadata< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > labels< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/instance< / span > : < span style = "color:#ae81ff" > estradiol-cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > spec< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > type< / span > : < span style = "color:#ae81ff" > ClusterIP< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > selector< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/instance< / span > : < span style = "color:#ae81ff" > estradiol-cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > ports< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > http< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > port< / span > : < span style = "color:#ae81ff" > 80< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > protocol< / span > : < span style = "color:#ae81ff" > TCP< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > targetPort< / span > : < span style = "color:#ae81ff" > http< / span >
< / span > < / span > < / code > < / pre > < / div >
< / details >
< / p >
< p > next, i need an < a href = "https://kubernetes.io/docs/concepts/services-networking/ingress/" > < code > Ingress< / code > < / a > to handle traffic inbound to the cluster
and direct it to the < code > Service< / code > :< / p >
< p >
< details >
< summary > < code > kubectl apply -f https://estradiol.cloud/posts/hugo-on-k8s-nginx/ingress.yaml< / code > < / summary >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-yaml" data-lang = "yaml" > < span style = "display:flex;" > < span > < span style = "color:#75715e" > # ingress.yaml< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > apiVersion< / span > : < span style = "color:#ae81ff" > networking.k8s.io/v1< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > kind< / span > : < span style = "color:#ae81ff" > Ingress< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > metadata< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > labels< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/instance< / span > : < span style = "color:#ae81ff" > estradiol-cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > app.kubernetes.io/name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > spec< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > rules< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > host< / span > : < span style = "color:#ae81ff" > estradiol.cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > http< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > paths< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#f92672" > backend< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > service< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > port< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > http< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > path< / span > : < span style = "color:#ae81ff" > /< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > pathType< / span > : < span style = "color:#ae81ff" > Prefix< / span >
< / span > < / span > < / code > < / pre > < / div >
< / details >
< / p >
< p > this part expresses a routing rule: traffic reaching the cluster via
< code > estradiol.cloud< / code > should go to my < code > Service< / code > , and then to one of its backend < code > Pod< / code > s.
to actually apply this rule, i need an ingress controller. mine is
< a href = "https://kubernetes.github.io/ingress-nginx/" > ingress-nginx< / a > .< / p >
2024-03-13 03:45:30 +00:00
< p > when i deployed controller in my cluster, it created < em > some more< / em > < code > nginx< / code > < code > Pod< / code > s.
these update their configuration dynamically based on the rules
2024-03-12 23:53:26 +00:00
in my < code > Ingress< / code > resource(s). the controller also also creates a < code > Service< / code > of
type < code > LoadBalancer< / code > , which < a href = "https://docs.digitalocean.com/products/kubernetes/how-to/add-load-balancers/" > magically< / a > creates a load balancer appliance
in my cloud provider. off-screen, i can point DNS to < em > that< / em > appliance to finish
the setup.< / p >
< p > < a href = "https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress" > < img src = "https://kubernetes.io/docs/images/ingress.svg" alt = "diagram: kubernetes ingress" > < / a > < / p >
< p > you can tell it’ s working by looking at your browser bar.< / p >
< hr >
< p > as this has come together, i’ ve gotten increasingly anxious about how much
YAML i’ ve had to write. this is a problem because YAML is software and, as
established, i’ m hoping not to have much of that. it’ s also annoying that most
of this YAML really is just boilerplate.< / p >
< p > conveniently, < a href = "https://bitnami.com/" > Bitnami< / a > maintains a < a href = "https://helm.sh" > Helm< / a > Chart that templates
out all the boilerplate and does exactly what i’ ve just been doing.< sup id = "fnref:8" > < a href = "#fn:8" class = "footnote-ref" role = "doc-noteref" > 8< / a > < / sup > i can
replace all my YAML with a call out to this chart and a few lines of
configuration, assuming i have < a href = "https://helm.sh/docs/intro/install/" > helm client installed< / a > :< / p >
< p >
< details >
< summary > < code > helm upgrade --install --create-namespace --namespace estradiol-cloud -f https://estradiol.cloud/posts/hugo-on-k8s-nginx/values.yaml oci://registry-1.docker.io/bitnamicharts/nginx< / code > < / summary >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-yaml" data-lang = "yaml" > < span style = "display:flex;" > < span > < span style = "color:#75715e" > # values.yaml< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > cloneStaticSiteFromGit< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > enabled< / span > : < span style = "color:#66d9ef" > true< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > repository< / span > : < span style = "color:#e6db74" > " https://code.estradiol.cloud/tamsin/estradiol.cloud.git" < / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > branch< / span > : < span style = "color:#ae81ff" > trunk< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > gitClone< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > command< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#ae81ff" > /bin/bash< / span >
< / span > < / span > < span style = "display:flex;" > < span > - -< span style = "color:#ae81ff" > ec< / span >
< / span > < / span > < span style = "display:flex;" > < span > - |< span style = "color:#e6db74" >
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > [[ -f " /opt/bitnami/scripts/git/entrypoint.sh" ]] & & source " /opt/bitnami/scripts/git/entrypoint.sh"
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > git clone {{ .Values.cloneStaticSiteFromGit.repository }} --no-checkout --branch {{ .Values.cloneStaticSiteFromGit.branch }} /tmp/app
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > [[ " $?" -eq 0 ]] & & cd /tmp/app & & git sparse-checkout init --cone & & git sparse-checkout set public & & git checkout & & shopt -s dotglob & & rm -rf /app/* & & mv /tmp/app/* /app/< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > ingress< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > enabled< / span > : < span style = "color:#66d9ef" > true< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > hostname< / span > : < span style = "color:#ae81ff" > estradiol.cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > ingressClassName< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > tls< / span > : < span style = "color:#66d9ef" > true< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > annotations< / span > : {
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > cert-manager.io/cluster-issuer< / span > : < span style = "color:#ae81ff" > letsencrypt-prod< / span >
< / span > < / span > < span style = "display:flex;" > < span > }
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > serverBlock< / span > : |-< span style = "color:#e6db74" >
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > server {
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > listen 8080;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > root /app/public;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > index index.html;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > }< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > service< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > type< / span > : < span style = "color:#ae81ff" > ClusterIP< / span >
< / span > < / span > < / code > < / pre > < / div >
< / details >
< / p >
< p > < img src = "images/hugo-helm-setup.svg" alt = "diagram: helm setup" > < / p >
< p > configuration for the < code > git-clone< / code > script and our custom server block are added
via < code > values.yaml< / code > . the < code > git-pull< / code > loop configured by the chart works as-is.
by using the chart, we get a few other nicities. for instance,
my < code > Pod< / code > s are now managed by a < a href = "https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" > < code > Deployment< / code > < / a > .< sup id = "fnref:9" > < a href = "#fn:9" class = "footnote-ref" role = "doc-noteref" > 9< / a > < / sup > this will make my
grand scale-out plans a breeze.< / p >
< h2 id = "getting-fluxd" > Getting Flux’ d< / h2 >
< p > by now, i’ m riding high. my whole setup is my static site code and < 30 lines of
YAML.< / p >
< p > i < em > do< / em > have a bunch of stuff deployed into my cluster, and none of this is very
reproducible without all of that. my workflow has also expanded to:< / p >
< ol >
< li > for routine site deploys:
< ol >
< li > make changes to source;< / li >
< li > run < code > hugo --gc --minify< / code > ;< sup id = "fnref1:5" > < a href = "#fn:5" class = "footnote-ref" role = "doc-noteref" > 5< / a > < / sup > < / li >
< li > < code > git< / code > commit & push.< / li >
< / ol >
< / li >
< li > to update < code > nginx< / code > , the chart version, or change config:
< ol >
< li > make changes to < code > values.yaml< / code > < / li >
< li > < code > helm upgrade< / code > < / li >
< / ol >
< / li >
< / ol >
2024-03-13 04:01:27 +00:00
< p > i could do without the extra < code > helm< / code > client dependency on my laptop. i’ m also
2024-03-12 23:53:26 +00:00
pretty < code > git push< / code > -pilled, and i really want the solution to all my problems
to take the now familiar shape: put a control loop in my cluster and push
to a < code > git< / code > repository.< / p >
< p > enter < a href = "https://fluxcd.io/" > < code > flux< / code > < / a > .< / p >
< p > with < code > flux< / code > , i decide on a repository (and maybe a path within it) to act as
a source for my Kubernetes YAML. i go through a short < a href = "https://fluxcd.io/flux/installation/bootstrap/" > bootstrap< / a >
process which installs the < code > flux< / code > controllers and add them to repository. to
make a change to a resource in my cluster, i edit the YAML and push to the
repository. < code > flux< / code > listens and applies the changes.< / p >
< p > < code > flux< / code > supports Helm deploys, so i can get that < code > helm< / code > client off my laptop.
i can also use it to manage my ingress controller, < code > cert-manager< / code > , < code > flux< / code >
itself and whatever other infrastructural junk i may end up needing.< / p >
< p > to move my web stack into < code > flux< / code > , i create a < code > HelmRepository< / code > resource for
the < code > bitnami< / code > Helm charts:< / p >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-yaml" data-lang = "yaml" > < span style = "display:flex;" > < span > < span style = "color:#75715e" > # bitnami-helm.yaml< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > apiVersion< / span > : < span style = "color:#ae81ff" > source.toolkit.fluxcd.io/v1beta2< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > kind< / span > : < span style = "color:#ae81ff" > HelmRepository< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > metadata< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > bitnami< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > namespace< / span > : < span style = "color:#ae81ff" > default< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > spec< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > url< / span > : < span style = "color:#ae81ff" > https://charts.bitnami.com/bitnami< / span >
< / span > < / span > < / code > < / pre > < / div > < p > and add a < code > HelmRelease< / code > pointing to the repository/chart version and containing
my < code > values.yaml< / code > :< / p >
< p >
< details >
< summary > < code > release.yaml< / code > < / summary >
< div class = "highlight" > < pre tabindex = "0" style = "color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;" > < code class = "language-yaml" data-lang = "yaml" > < span style = "display:flex;" > < span > < span style = "color:#f92672" > apiVersion< / span > : < span style = "color:#ae81ff" > helm.toolkit.fluxcd.io/v2beta1< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > kind< / span > : < span style = "color:#ae81ff" > HelmRelease< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > metadata< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > web< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > namespace< / span > : < span style = "color:#ae81ff" > estradiol-cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > spec< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > interval< / span > : < span style = "color:#ae81ff" > 5m< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > chart< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > spec< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > chart< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > version< / span > : < span style = "color:#e6db74" > ' 15.12.2' < / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > sourceRef< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > kind< / span > : < span style = "color:#ae81ff" > HelmRepository< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > name< / span > : < span style = "color:#ae81ff" > bitnami< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > namespace< / span > : < span style = "color:#ae81ff" > default< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > interval< / span > : < span style = "color:#ae81ff" > 1m< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > values< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > cloneStaticSiteFromGit< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > enabled< / span > : < span style = "color:#66d9ef" > true< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > repository< / span > : < span style = "color:#e6db74" > " https://code.estradiol.cloud/tamsin/estradiol.cloud.git" < / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > branch< / span > : < span style = "color:#ae81ff" > trunk< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > gitClone< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > command< / span > :
< / span > < / span > < span style = "display:flex;" > < span > - < span style = "color:#ae81ff" > /bin/bash< / span >
< / span > < / span > < span style = "display:flex;" > < span > - -< span style = "color:#ae81ff" > ec< / span >
< / span > < / span > < span style = "display:flex;" > < span > - |< span style = "color:#e6db74" >
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > [[ -f " /opt/bitnami/scripts/git/entrypoint.sh" ]] & & source " /opt/bitnami/scripts/git/entrypoint.sh"
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > git clone {{ .Values.cloneStaticSiteFromGit.repository }} --no-checkout --branch {{ .Values.cloneStaticSiteFromGit.branch }} /tmp/app
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > [[ " $?" -eq 0 ]] & & cd /tmp/app & & git sparse-checkout init --cone & & git sparse-checkout set public & & git checkout & & shopt -s dotglob & & rm -rf /app/* & & mv /tmp/app/* /app/< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > ingress< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > enabled< / span > : < span style = "color:#66d9ef" > true< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > hostname< / span > : < span style = "color:#ae81ff" > estradiol.cloud< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > ingressClassName< / span > : < span style = "color:#ae81ff" > nginx< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > tls< / span > : < span style = "color:#66d9ef" > true< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > annotations< / span > : {
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > cert-manager.io/cluster-issuer< / span > : < span style = "color:#ae81ff" > letsencrypt-prod< / span >
< / span > < / span > < span style = "display:flex;" > < span > }
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > serverBlock< / span > : |-< span style = "color:#e6db74" >
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > server {
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > listen 8080;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > root /app/public;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > index index.html;
< / span > < / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#e6db74" > }< / span >
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > service< / span > :
< / span > < / span > < span style = "display:flex;" > < span > < span style = "color:#f92672" > type< / span > : < span style = "color:#ae81ff" > ClusterIP< / span >
< / span > < / span > < / code > < / pre > < / div >
< / details >
< / p >
< p > when i push these to my < code > flux< / code > < a href = "https://gitlab.com/no_reply/sublingual/-/tree/trunk/estradiol.cloud" > source repository< / a > , the Helm
release rolls out.< / p >
< p > < img src = "images/flux-seq.svg" alt = "diagram: flux git push/deploy sequence" > < / p >
< h2 id = "a-note-about-software" > A Note About Software< / h2 >
< p > in the end, i’ m forced to admit there’ s still a lot of software involved in all
of this. setting aside the stuff that provisions and scales my cluster nodes,
and the < em > magic< / em > < code > LoadBalancer< / code > , i have:< / p >
< ul >
< li > < code > nginx< / code > (running from a stock image);< / li >
< li > < code > git< / code > & < code > bash< / code > (running from a stock image);< / li >
< li > a remote git server (i’ m running < code > gitea< / code > < sup id = "fnref:10" > < a href = "#fn:10" class = "footnote-ref" role = "doc-noteref" > 10< / a > < / sup > , but github dot com is fine here);< / li >
< li > Kubernetes (oops!);
< ul >
< li > < code > flux< / code > , especially < code > kustomize-controller< / code > and < code > helm-controller< / code > ;< / li >
< li > < code > ingress-nginx< / code > controller;< / li >
< li > < code > cert-manager< / code > and Let’ s Encrypt;< / li >
< / ul >
< / li >
< li > the < code > bitnami/nginx< / code > Helm chart;< / li >
< / ul >
< p > the bulk of this i’ ll be able to reuse for the other things i deploy on the
cluster< sup id = "fnref:11" > < a href = "#fn:11" class = "footnote-ref" role = "doc-noteref" > 11< / a > < / sup > . and it replaces SASS black-boxes like “ AWS Amplify, CloudCannon,
Cloudflare Pages, GitHub Pages, GitLab Pages, and Netlify” in the recommended
Hugo deployment.< / p >
< p > to actually deploy my site, i get to maintain a < code > bash< / code > scripts for < code > git-clone< / code > , my
NGINX config, and a couple of blobs of YAML.< / p >
< p > at least there are no webhooks.< / p >
< hr >
< p > < em > fin< / em > < / p >
< div class = "footnotes" role = "doc-endnotes" >
< hr >
< ol >
< li id = "fn:1" >
< p > i appreciate the culinary branding.  < a href = "#fnref:1" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:2" >
< p > unlikely.  < a href = "#fnref:2" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:3" >
< p > few of which could be considered relevant for my project.  < a href = "#fnref:3" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:4" >
< p > i absolutely will not need this  < a href = "#fnref:4" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:5" >
< p > i added < code > disableHTML = true< / code > and < code > disableXML = true< / code > to < code > [minify]< / code >
configuration in < code > hugo.toml< / code > to keep HTML and RSS diffs readable.  < a href = "#fnref:5" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a >   < a href = "#fnref1:5" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:6" >
< p > i can check that its working, at least, with a < a href = "https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/" > port-forward< / a > .  < a href = "#fnref:6" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:7" >
< p > lmao  < a href = "#fnref:7" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:8" >
< p > what incredible luck! (obviously, until now i’ ve been working backward from this chart)  < a href = "#fnref:8" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:9" >
< p > i also snuck a TLS certificate configuration via Let’ s Encrypt with
2024-03-13 04:06:40 +00:00
< a href = "https://cert-manager.io/docs/tutorials/acme/nginx-ingress/" > < code > cert-manager< / code > < / a > into this iteration. if you’ re following along at home and don’ t have < code > cert-manager< / code > installed, this should still work fine (but with no HTTPS).  < a href = "#fnref:9" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
2024-03-12 23:53:26 +00:00
< / li >
< li id = "fn:10" >
< p > because i’ m running < code > gitea< / code > in my cluster and i want to avoid a circular
dependency for my < code > flux< / code > source repository, i also depend on GitLab dot com.  < a href = "#fnref:10" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< li id = "fn:11" >
< p > i won’ t.  < a href = "#fnref:11" class = "footnote-backref" role = "doc-backlink" > ↩ ︎ < / a > < / p >
< / li >
< / ol >
< / div >
< / div >
< footer class = "content__footer" > < / footer >
< / section >
< section class = "page__aside" >
< div class = "aside__about" >
< div class = "aside__about" >
< h1 class = "about__title" > it' s estradiol.cloud!< / h1 >
< p class = "about__description" > < blockquote >
< p > < a href = "https://doi.org/10.5749/minnesota/9780816650477.003.0001" > the regrown limb can be monstrous, duplicated, potent. We have all been injured, profoundly.< / a > < / p >
< / blockquote >
< hr >
2024-03-13 03:55:20 +00:00
< p > Ь 887 | 2< / p >
2024-03-12 23:53:26 +00:00
< / p >
< / div >
< ul class = "aside__social-links" >
< li >
< i class = "fa-brands fa-mastodon" > < / i > < a href = "https://hachyderm.io/@no_reply" rel = "me" title = "Hachyderm" > hachyderm.io/@no_reply< / a >
< / li >
< li >
< i class = "fa-brands fa-mastodon" > < / i > < a href = "https://chaosfem.tw/@t4tamsin" rel = "me" title = "Chaosfem" > < / i > chaosfem.tw/@t4tamsin< / a >
< / li >
< li >
< i class = "fa-brands fa-git-alt" > < / i > < a href = "https://code.estradiol.cloud" rel = "me" title = "Code" > code< / a >
< / li >
< li >
< i class = "fa-brands fa-gitlab" > < / i > < a href = "https://gitlab.com/no-reply" rel = "me" title = "Code" > work code< / a >
< / li >
< li >
< i class = "fa-brands fa-github" > < / i > < a href = "https://github.com/no_eply" rel = "me" title = "Code" > more code< / a >
< / li >
< / ul >
< / div >
< hr >
< div class = "aside__content" >
< p > kubernetes is for girls< / p >
< p >
2024-03-12
< / p >
< hr >
Hugo on Kubernetes & NGINX:
< nav id = "TableOfContents" >
< ol >
< li > < a href = "#getting-started" > Getting Started< / a > < / li >
< li > < a href = "#getting-static" > Getting Static< / a > < / li >
< li > < a href = "#getting-web" > Getting Web< / a > < / li >
< li > < a href = "#getting-fluxd" > Getting Flux’ d< / a > < / li >
< li > < a href = "#a-note-about-software" > A Note About Software< / a > < / li >
< / ol >
< / nav >
< / div >
< / section >
< footer class = "page__footer" > < / footer >
< / div >
< / body >
< / html >