Documentation for Kubernetes Cluster Setup
This document provides a step-by-step guide to set up a Kubernetes cluster on Ubuntu nodes, including the installation of necessary packages, configuration of container runtime, and setup of Kubernetes components. Additionally, it covers the setup of load balancing using Keepalived and HAProxy, and the deployment of monitoring tools like Prometheus and Grafana.
Requement.
- OS version: Ubuntu 22.04.4 LTS
- Proxy: 10.237.7.250:3128
- Kube version: kubelet=1.28.8-1.1, kubectl=1.28.8-1.1, kubeadm=1.28.8-1.1
- HAProxy version: 2.4.24
- Keepalived verison: v2.2.4
- Metallb version: v0.13.5
- Calico versionv3.29.2
- Kube Prometheus stack: chart version 34.9.0, app version 0.55.0
- Helm version: chart version 2.0.1, app version 4.0.1
- NGINX Ingress Controller 4.0.1
Summary steps:
-
Update and Install Dependencies: - Update package lists and install required packages such as
curl,gnupg2,software-properties-common,apt-transport-https, andca-certificates. - Disable and stop the firewall (ufw). -
Install and Configure Containerd: - Install
containerdand configure it to use systemd as the cgroup driver. - Set up HTTP proxy for containerd if required. -
Install Kubernetes Components: - Add Kubernetes apt repository and install specific versions of
kubeadm,kubelet, andkubectl. - Enable and configurekubelet. -
Kernel and System Configuration: - Configure kernel parameters for Kubernetes networking. - Disable swap.
-
Load Balancer Setup: - Install and configure Keepalived for high availability. - Install and configure HAProxy for load balancing Kubernetes API server and worker nodes.
-
Initialize Kubernetes Cluster: - Initialize the Kubernetes control plane using
kubeadm. - Set up kubeconfig for kubectl access. - Join worker nodes to the cluster. -
Network Plugin Installation: - Install Calico as the network plugin for the cluster.
-
Install Helm: - Download and install Helm for managing Kubernetes applications.
-
Deploy NGINX Ingress Controller: - Install NGINX Ingress Controller using Helm and configure it to use host ports.
-
Monitoring Setup: - Install Prometheus and Grafana using Helm for monitoring the cluster. - Configure MetalLB for load balancing services.
-
Prometheus Deployment: - Deploy Prometheus using a custom YAML configuration. - Configure the service type for Prometheus to LoadBalancer or NodePort as needed.
This guide ensures a comprehensive setup of a Kubernetes cluster with high availability, load balancing, and monitoring capabilities.
Detail steps:
Update package lists on all nodes.
apt-get update
Install necessary packages:
apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
isable UFW (Uncomplicated Firewall):
ufw disable
systemctl stop ufw
systemctl disable ufw
Install Docker and containerd:
These commands install Docker's GPG key, add Docker's repository, update the package list, and install containerd, a container runtime.
apt-get install ca-certificates curl gnupg lsb-release -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install containerd.io -y
containerd --version
Add Kubernetes repository and install Kubernetes components:
These commands add the Kubernetes repository, update the package list, and install specific versions of kubelet, kubectl, and kubeadm.
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list
apt update
apt list -a kubeadm
apt-get install -y kubelet=1.28.8-1.1 kubectl=1.28.8-1.1 kubeadm=1.28.8-1.1
systemctl enable kubelet
Configure sysctl for Kubernetes
This creates a sysctl configuration file to enable packet forwarding and bridge network traffic.
tee /etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
Increase connection tracking table size:
This increases the maximum number of tracked connections.
echo "net.netfilter.nf_conntrack_max=1000000" >> /etc/sysctl.conf
Load necessary kernel modules:
These commands load the kernel modules and apply the sysctl settings.
tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
Load the modules immediately and apply sysctl settings:
These commands load the kernel modules and apply the sysctl settings.
modprobe overlay
modprobe br_netfilter
sysctl --system
Disable swap:
These commands disable swap, which is necessary for Kubernetes to function properly.
sed -i "/ swap / s/^\(.*\)$/#\1/g" /etc/fstab || sed -i '/swap/d' /etc/fstab
swapoff -a
Configure containerd:
These commands create the containerd configuration directory, generate a default configuration file, and modify it to use systemd as the cgroup driver.
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
Set up HTTP proxy for containerd:
These commands create a systemd drop-in configuration file to set HTTP proxy environment variables for containerd.
mkdir -p /etc/systemd/system/containerd.service.d
cat > /etc/systemd/system/containerd.service.d/http-proxy.conf << 'OEF'
[Service]
Environment="HTTP_PROXY=http://10.237.7.250:3128"
Environment="HTTPS_PROXY=http://10.237.7.250:3128"
Environment="NO_PROXY=10.237.7.0/24,127.0.0.1,localhost,10.96.0.0/12,10.244.0.0/16"
OEF
These commands reload systemd configurations, enable containerd to start on boot, restart containerd, check its status, and display its environment variables.
systemctl daemon-reload
systemctl enable containerd
systemctl restart containerd
systemctl is-active containerd
systemctl show --property=Environment containerd
Pull Kubernetes images:
Pull all images
kubeadm config images pull
Install Keepalived
apt-get install linux-headers-$(uname -r)
apt-get update
apt-get install keepalived -y
Create /etc/keepalived/keepalived.conf
cat > /etc/keepalived/keepalived.conf << 'OEF'
vrrp_instance apiserver {
interface ens160
virtual_router_id 101
virtual_ipaddress {
10.237.7.79
}
}
OEF
Restart Keepalived
systemctl restart keepalived
systemctl enable keepalived
systemctl status keepalived
Install HAProxy
apt-get update
apt-get install haproxy -y
Create /etc/haproxy/haproxy.cfg
cat > /etc/haproxy/haproxy.cfg << 'OEF'
frontend stats
bind *:8080
mode http
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST
frontend fe-apiserver
bind 0.0.0.0:6443
mode tcp
option tcplog
default_backend be-apiserver
backend be-apiserver
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server k8s-master1 10.237.7.71:6443 check
server k8s-master2 10.237.7.72:6443 check
server k8s-master3 10.237.7.73:6443 check
frontend http_frontend
bind *:80
mode tcp
option tcplog
default_backend http_backend
backend http_backend
mode tcp
balance roundrobin
server k8s-worker1 10.237.7.74:30100 check
server k8s-worker2 10.237.7.75:30100 check
server k8s-worker3 10.237.7.76:30100 check
frontend https_frontend
bind *:443
mode tcp
option tcplog
default_backend https_backend
backend https_backend
mode tcp
balance roundrobin
server k8s-worker1 10.237.7.74:30101 check
server k8s-worker2 10.237.7.75:30101 check
server k8s-worker3 10.237.7.76:30101 check
OEF
Restart HAProxy
systemctl enable haproxy
systemctl restart haproxy
systemctl status haproxy
Set hostname all nodes
hostnamectl set-hostname k8s-master1
hostnamectl set-hostname k8s-master2
hostnamectl set-hostname k8s-master3
hostnamectl set-hostname k8s-worker1
hostnamectl set-hostname k8s-worker2
hostnamectl set-hostname k8s-worker3
Set hostfile
cat >> /etc/hosts << 'OEF'
10.237.7.71 k8s-master1
10.237.7.72 k8s-master2
10.237.7.73 k8s-master3
10.237.7.74 k8s-worker1
10.237.7.75 k8s-worker2
10.237.7.76 k8s-worker3
OEF
Init cluster
kubeadm init --control-plane-endpoint "10.237.7.79:6443" --upload-certs --pod-network-cidr="10.244.0.0/16" --v=5
Create env
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
Create master token
shell> kubeadm token create --print-join-command --certificate-key $(kubeadm init phase upload-certs --upload-certs | tail -1)
kubeadm join 10.237.7.79:6443 --token rxvhse.c171fivq1209642u --discovery-token-ca-cert-hash sha256:80f472a531bd08542cee645e8ad8fdf95b5f54e7663fbaad606d73a15cd35d5a --control-plane --certificate-key 7dae022de6eac3f6fa3256748e0058d4a4f523667969aa060784d8b7db14537d
Create workder token
shell> kubeadm token create --print-join-command
kubeadm join 10.237.7.79:6443 --token 5v78oh.e3zm61i2d2dk2bbl --discovery-token-ca-cert-hash sha256:80f472a531bd08542cee645e8ad8fdf95b5f54e7663fbaad606d73a15cd35d5a
Deploy Calico network
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/calico.yaml
wget https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/calico.yaml
sed -i 's/# - name: CALICO_IPV4POOL_CIDR/- name: CALICO_IPV4POOL_CIDR/' calico.yaml
sed -i 's|# value:.*| value: "10.244.0.0/16"|g' calico.yaml
kubectl apply -f calico.yaml
kubectl get pods -A -o wide
kubectl get node -A -o wide
Heml install
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh && ./get_helm.sh
helm version
Make nginx-ingress namespace
kubectl create namespace nginx-ingress
helm repo add nginx-stable https://helm.nginx.com/stable
helm install ingress nginx-stable/nginx-ingress --namespace nginx-ingress
git clone https://github.com/nginxinc/kubernetes-ingress.git
Set proxy
export http_proxy=http://10.237.7.250:3128
export https_proxy=http://10.237.7.250:3128
export no_proxy=localhost,127.0.0.1,10.237.7.0/24
Verify
helm list --namespace nginx-ingress
helm status ingress --namespace nginx-ingress
Make custom-values.yaml
cat > custom-values.yaml << 'OEF'
controller:
kind: daemonset
daemonset:
useHostPort: true
hostPorts:
http: 80
https: 443
service:
type: NodePort
nodePorts:
http: 30100
https: 30101
OEF
Upgrade nginx-ingress
helm upgrade ingress nginx-stable/nginx-ingress --namespace nginx-ingress -f ./custom-values.yaml
Verify
kubectl get po -n nginx-ingress
kubectl get ds -n nginx-ingress
kubectl get svc -n nginx-ingress
Patch config map
echo '{
"data": {
"use-proxy-protocol": "true",
"proxy-connect-timeout": "10s",
"proxy-read-timeout": "10s",
"client-max-body-size": "2m",
"external-status-address": "10.237.7.79"
}
}' > ./patch-configmap.json
Apply new config map
kubectl patch configmap ingress-nginx-ingress -n nginx-ingress --patch "$(cat ./patch-configmap.json)"
kubectl -n nginx-ingress get cm
kubectl -n nginx-ingress get cm/ingress-nginx-ingress -o yaml
kubectl -n nginx-ingress patch svc ingress-nginx-ingress-controller --patch '{"spec": { "type": "NodePort", "ports": [ { "port": 80, "nodePort": 30100 }, { "port": 443, "nodePort": 30101 } ] } }'
kubectl get svc -n nginx-ingress
Create metric server
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Apply metric server
vi ./components.yaml
add line ```kubelet-insecure-tls``
kubectl apply -f ./components.yaml
### PROMETHEUS ###
mkdir -p /home/prometheus
cd /home/prometheus
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add stable https://charts.helm.sh/stable
helm repo update
helm search repo prometheus |egrep "stack|CHART"
helm pull prometheus-community/kube-prometheus-stack --version 34.9.0
tar -xzf kube-prometheus-stack-34.9.0.tgz
cp kube-prometheus-stack/values.yaml values-prometheus.yaml
kubectl create ns kube-monitoring
helm -n kube-monitoring install prometheus-grafana-stack -f /home/prometheus/values-prometheus.yaml kube-prometheus-stack
helm -n kube-monitoring uninstall prometheus-grafana-stack -f /home/prometheus/values-prometheus.yaml kube-prometheus-stack
helm -n kube-monitoring upgrade prometheus-grafana-stack -f /home/prometheus/values-prometheus.yaml kube-prometheus-stack
kubectl -n kube-monitoring get all
kubectl get ingress -n kube-monitoring -owide
Metallb
Change strictARP: false -> strictARP: true
# see what changes would be made, returns nonzero returncode if different
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl diff -f - -n kube-system
# actually apply the changes, returns nonzero returncode on errors only
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system
Apply MetaBL
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.5/config/manifests/metallb-native.yaml
Create IPAddressPool
cat << OEF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 10.237.7.80-10.237.7.90
OEF
cat << OEF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
OEF
cat > ./prometheus_deployment.yaml << OEF
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
spec:
selector:
matchLabels:
app: monitor
replicas: 1
template:
metadata:
labels:
app: monitor
spec:
containers:
- name: prometheus
image: prom/prometheus
ports:
- containerPort: 9090
resources:
limits:
memory: "150M"
cpu: "100m"
---
apiVersion: v1
kind: Service
metadata:
name: prometheus-service
spec:
selector:
app: monitor
type: LoadBalancer
ports:
- name: http
port: 9090
targetPort: 9090
OEF
Apply
kubectl apply -f ./prometheus_deployment.yaml
kubectl get svc/prometheus-service
Patch LoadBalancer -> NodePort
kubectl patch svc prometheus-service -p '{"spec": {"type": "NodePort"}}'
kubectl patch svc prometheus-service -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "nodePort": 30090}]}}'
Rollback to LoadBalancer
kubectl patch svc prometheus-service -p '{"spec": {"type": "LoadBalancer"}}'