All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 14s
223 lines
4.9 KiB
Markdown
223 lines
4.9 KiB
Markdown
# Kubernetes
|
|
|
|
- [Kubernetes](#kubernetes)
|
|
- [Setup](#setup)
|
|
- [MetalLB](#metallb)
|
|
- [Ingress Nginx](#ingress-nginx)
|
|
- [Cert Manager](#cert-manager)
|
|
- [Storage](#storage)
|
|
|
|
<https://wiki.archlinux.org/title/Kubernetes>
|
|
|
|
## Setup
|
|
|
|
```bash
|
|
pacman -S kubeadm kubelet containerd cni-plugins cilium-cli helm kubectl
|
|
```
|
|
|
|
/etc/modules-load.d/k8s.conf
|
|
|
|
```conf
|
|
overlay
|
|
br_netfilter
|
|
```
|
|
|
|
/etc/sysctl.d/k8s.conf
|
|
|
|
```conf
|
|
net.bridge.bridge-nf-call-iptables = 1
|
|
net.bridge.bridge-nf-call-ip6tables = 1
|
|
net.ipv4.ip_forward = 1
|
|
```
|
|
|
|
/etc/containerd/config.toml
|
|
|
|
```toml
|
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
|
...
|
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
|
|
SystemdCgroup = true
|
|
```
|
|
|
|
```bash
|
|
reboot
|
|
mkdir /etc/containerd
|
|
containerd config default > /etc/containerd/config.toml
|
|
systemctl enable --now containerd
|
|
systemctl enable --now kubelet
|
|
kubeadm init --pod-network-cidr='10.244.0.0/16'
|
|
|
|
mkdir -p $HOME/.kube
|
|
cp /etc/kubernetes/admin.conf $HOME/.kube/config
|
|
chown $(id -u):$(id -g) $HOME/.kube/config
|
|
|
|
cilium-cli install
|
|
|
|
# Note the "-" at the end, this removes the taint
|
|
kubectl taint node kube node-role.kubernetes.io/control-plane:NoSchedule-
|
|
```
|
|
|
|
## MetalLB
|
|
|
|
Install with helm:
|
|
|
|
```bash
|
|
helm repo add metallb https://metallb.github.io/metallb
|
|
helm install metallb metallb/metallb -n kube-system
|
|
```
|
|
|
|
You must create a production pool if IP Addresses. Apply the following config
|
|
(substituting your public IP address space)
|
|
|
|
```yaml
|
|
apiVersion: metallb.io/v1beta1
|
|
kind: IPAddressPool
|
|
metadata:
|
|
name: production
|
|
namespace: kube-system
|
|
spec:
|
|
# Production services will go here. Public IPs are expensive, so we leased
|
|
# just 4 of them.
|
|
addresses:
|
|
- 192.168.122.206/32
|
|
```
|
|
|
|
Here is an example service which allows IP sharing and uses the "production" address pool.
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: ingress-nginx-demo
|
|
annotations:
|
|
metallb.universe.tf/address-pool: production
|
|
metallb.universe.tf/allow-shared-ip: "nginx"
|
|
spec:
|
|
type: LoadBalancer
|
|
externalTrafficPolicy: Cluster
|
|
selector:
|
|
app.kubernetes.io/name: ingress-nginx-demo
|
|
ports:
|
|
- name: ingress-nginx-demo
|
|
protocol: TCP
|
|
port: 8000
|
|
targetPort: http
|
|
```
|
|
|
|
## Ingress Nginx
|
|
|
|
Now we need an ingress solution (preferably with certs for https). We'll be using nginx since
|
|
it's a little bit more configurable than traefik (though don't sell traefik short, it's really
|
|
good. Just finnicky when you have use cases they haven't explicitly coded for).
|
|
|
|
```bash
|
|
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
|
|
helm repo update
|
|
helm upgrade --install \
|
|
ingress-nginx \
|
|
ingress-nginx/ingress-nginx \
|
|
--values ingress-nginx-values.yaml \
|
|
--namespace ingress-nginx \
|
|
--create-namespace
|
|
```
|
|
|
|
## Cert Manager
|
|
|
|
Cert manager handles automatic TLS for our ingress with Let's Encrypt.
|
|
|
|
Install with helm:
|
|
|
|
```bash
|
|
helm repo add jetstack https://charts.jetstack.io
|
|
helm repo update
|
|
helm upgrade --install \
|
|
cert-manager jetstack/cert-manager \
|
|
--namespace cert-manager \
|
|
--create-namespace \
|
|
--version v1.12.4 \
|
|
--set installCRDs=true
|
|
```
|
|
|
|
Now we need to create an issuer. Apply the following config:
|
|
|
|
```yaml
|
|
apiVersion: cert-manager.io/v1
|
|
kind: ClusterIssuer
|
|
metadata:
|
|
name: letsencrypt
|
|
spec:
|
|
acme:
|
|
# The ACME server URL
|
|
server: https://acme-v02.api.letsencrypt.org/directory
|
|
# Email address used for ACME registration
|
|
email: nginx@ducoterra.net
|
|
# Name of a secret used to store the ACME account private key
|
|
privateKeySecretRef:
|
|
name: letsencrypt
|
|
# Enable the HTTP-01 challenge provider
|
|
solvers:
|
|
- http01:
|
|
ingress:
|
|
class: nginx
|
|
```
|
|
|
|
Here's an example ingress definition:
|
|
|
|
```yaml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: ingress-nginx-demo
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt
|
|
kubernetes.io/ingress.class: nginx
|
|
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
|
nginx.org/client-max-body-size: "0"
|
|
spec:
|
|
rules:
|
|
- host: ingress-nginx-demo.reeseapps.com
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: ingress-nginx-demo
|
|
port:
|
|
number: 80
|
|
tls:
|
|
- hosts:
|
|
- ingress-nginx-demo.reeseapps.com
|
|
secretName: ingress-nginx-demo-tls-cert
|
|
```
|
|
|
|
## Storage
|
|
|
|
We can use host-path storage immediately like so:
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test-webserver
|
|
spec:
|
|
containers:
|
|
- name: test-webserver
|
|
image: registry.k8s.io/test-webserver:latest
|
|
volumeMounts:
|
|
- mountPath: /var/local/aaa
|
|
name: mydir
|
|
- mountPath: /var/local/aaa/1.txt
|
|
name: myfile
|
|
volumes:
|
|
- name: mydir
|
|
hostPath:
|
|
# Ensure the file directory is created.
|
|
path: /var/local/aaa
|
|
type: DirectoryOrCreate
|
|
- name: myfile
|
|
hostPath:
|
|
path: /var/local/aaa/1.txt
|
|
type: FileOrCreate
|
|
```
|