flesh out kubernetes install instructions
This commit is contained in:
215
arch/kubernetes.md
Normal file
215
arch/kubernetes.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# Kubernetes
|
||||
|
||||
<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
|
||||
```
|
||||
Reference in New Issue
Block a user