Overview
This document entails steps and procedures to install k8s in an offline environment without internet access, whether in the cloud (public or private), or on bare-metal hardware.
System Parameters/Versions Used for this Example:
-
Rocky Linux: 8.10
-
K8s: 1.29.12
-
Containerd: 1.7.23
-
Docker: 27.2.0
-
One computer/system with containerd/docker installed and internet access.
- recommend to use a system with the same chipset as installation system (i.e. AMD64)
-
Destination offline system for installation (no internet access).
Prerequisites
The following packages/dependencies should already be completed:
-
base operating system (OS) updated and patched
-
containerd or docker installed (both on-line and off-line systems)
-
firewalld installed
Prepare K8S Images/Binaries
System with Internet Access
Download all required binaries/images. Perform the following steps from the system with internet access. This example uses a linux machine.
Step 1: Set Version
Set desired K8S version:
Step 2: Download K8S Packages
Download all K8S packages for installation on Rocky 8. Set the repository:
# set repository and repo
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/$K8S_VERSION/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/$K8S_VERSION/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
Pull packages, saved in /k8s
directory:
sudo dnf install -y --downloadonly --downloaddir=/k8s kubelet kubeadm kubectl --disableexcludes=kubernetes
Compress directory for easier transfer:
tar -zcvf /k8s.tar.gz /k8s
Step 3 (optional): Determine Dependencies
Required dependencies are already listed in the following step, but can verify if necessary.
Check which version of K8S was downloaded:
Output should look similar to the following:
kubeadm-1.29.12-150500.1.1.x86_64.rpm
In this example, using v1.29.12
. Set variable for kubeadm
version:
export KUBEADM_VERSION=v1.29.12
Download kubeadm
binary, make executable, and move to bin:
# download
curl -L https://dl.k8s.io/release/$KUBEADM_VERSION/bin/linux/amd64/kubeadm -o kubeadm_$KUBEADM_VERSION
# move binary
sudo mv kubeadm_$KUBEADM_VERSION /usr/local/bin/kubeadm
# set permissions to execute
sudo chmod +x /usr/local/bin/kubeadm
List dependencies:
kubeadm config images list --kubernetes-version=$KUBEADM_VERSION
Output should be similar to the following:
registry.k8s.io/kube-apiserver:v1.29.12
registry.k8s.io/kube-controller-manager:v1.29.12
registry.k8s.io/kube-scheduler:v1.29.12
registry.k8s.io/kube-proxy:v1.29.12
registry.k8s.io/coredns/coredns:v1.11.1
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.16-0
Step 4: Prepare Dependency Images
Pull all required images, can use Docker
or containerd
.
Using Docker:
docker pull --platform=linux/amd64 registry.k8s.io/kube-apiserver:v1.29.12
docker pull --platform=linux/amd64 registry.k8s.io/kube-controller-manager:v1.29.12
docker pull --platform=linux/amd64 registry.k8s.io/kube-scheduler:v1.29.12
docker pull --platform=linux/amd64 registry.k8s.io/kube-proxy:v1.29.12
docker pull --platform=linux/amd64 registry.k8s.io/coredns/coredns:v1.11.1
docker pull --platform=linux/amd64 registry.k8s.io/pause:3.9
docker pull --platform=linux/amd64 registry.k8s.io/etcd:3.5.16-0
Save the images as compressed files so that they can be transferred to the offline system:
docker save -o kube-apiserver_v1.29.12.tar registry.k8s.io/kube-apiserver:v1.29.12
docker save -o kube-controller-manager_v1.29.12.tar registry.k8s.io/kube-controller-manager:v1.29.12
docker save -o kube-scheduler_v1.29.12.tar registry.k8s.io/kube-scheduler:v1.29.12
docker save -o kube-proxy_v1.29.12.tar registry.k8s.io/kube-proxy:v1.29.12
docker save -o coredns_v1.11.1.tar registry.k8s.io/coredns/coredns:v1.11.1
docker save -o pause_3.9.tar registry.k8s.io/pause:3.9
docker save -o etcd_3.5.16-0.tar registry.k8s.io/etcd:3.5.16-0
Using containerd:
ctr image pull --platform=linux/amd64 registry.k8s.io/kube-apiserver:v1.29.12
ctr image pull --platform=linux/amd64 registry.k8s.io/kube-controller-manager:v1.29.12
ctr image pull --platform=linux/amd64 registry.k8s.io/kube-scheduler:v1.29.12
ctr image pull --platform=linux/amd64 registry.k8s.io/kube-proxy:v1.29.12
ctr image pull --platform=linux/amd64 registry.k8s.io/coredns/coredns:v1.11.1
ctr image pull --platform=linux/amd64 registry.k8s.io/pause:3.9
ctr image pull --platform=linux/amd64 registry.k8s.io/etcd:3.5.16-0
Save the images as compressed files so that they can be transferred to the offline system:
ctr image export --platform=linux/amd64 kube-apiserver_v1.29.12.tar registry.k8s.io/kube-apiserver:v1.29.12
ctr image export --platform=linux/amd64 kube-controller-manager_v1.29.12.tar registry.k8s.io/kube-controller-manager:v1.29.12
ctr image export --platform=linux/amd64 kube-scheduler_v1.29.12.tar registry.k8s.io/kube-scheduler:v1.29.12
ctr image export --platform=linux/amd64 kube-proxy_v1.29.12.tar registry.k8s.io/kube-proxy:v1.29.12
ctr image export --platform=linux/amd64 coredns_v1.11.1.tar registry.k8s.io/coredns/coredns:v1.11.1
ctr image export --platform=linux/amd64 pause_3.9.tar registry.k8s.io/pause:3.9
ctr image export --platform=linux/amd64 etcd_3.5.16-0.tar registry.k8s.io/etcd:3.5.16-0
Step 5: Transfer Binaries/Images to Offline System
Transfer downloaded binaries and images to offline system. This can be done via secure ssh or removable storage media.
-
k8s.tar.gz
-
kube-apiserver_v1.29.12.tar
-
kube-controller-manager_v1.29.12.tar
-
kube-scheduler_v1.29.12.tar
-
kube-proxy_v1.29.12.tar
-
coredns_v1.11.1.tar
-
pause_3.9.tar
-
etcd_3.5.16-0.tar
Install K8S
Offline System without Internet Access
Import all binaries and images from the system with internet access to the offline system. This example uses a linux machine.
Commands have to be performed as root (since it involves installation of Kubernetes).
Step 1: Install K8S Packages
Unzip k8s.tar and install, then enable kubelet
:
# unzip k8s components
tar -zxvf k8s.tar.gz
# install k8s
rpm -ivh --replacefiles --replacepkgs /k8s/*.rpm
# enable kubelet
systemctl enable kubelet.service
systemctl start kubelet.service
# check status
sudo systemctl status kubelet
Step 2: Load K8S Dependency Images
Load K8S images with either docker
or containerd
(using containerd for this example):
sudo ctr -n=k8s.io images import kube-apiserver_v1.29.12.tar
sudo ctr -n=k8s.io images import kube-controller-manager_v1.29.12.tar
sudo ctr -n=k8s.io images import kube-scheduler_v1.29.12.tar
sudo ctr -n=k8s.io images import kube-proxy_v1.29.12.tar
sudo ctr -n=k8s.io images import coredns_v1.11.1.tar
sudo ctr -n=k8s.io images import pause_3.9.tar
sudo ctr -n=k8s.io images import etcd_3.5.16-0.tar
Step 3: Initialize K8S
Initialize and setup cluster control-plane node:
CNI_CIDR="192.168.100.0/19"
SERVICE_CIDR="192.168.200.0/19"
NODE_NAME="my-node"
kubeadm init \
--pod-network-cidr $CNI_CIDR \
--service-cidr $SERVICE_CIDR \
--node-name $NODE_NAME
NOTE: Ensure that CNI and Service CIDRs are consistent with previous or desired installation.
Set kubectl
config:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=/etc/kubernetes/admin.conf
Verify that the cluster is running:
Output should be similar to the following:
NAME STATUS ROLES AGE VERSION
ip-172-31-9-184.ec2.internal NotReady control-plane 37m v1.29.12
List running pods:
Output should be similar to the following:
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-76f75df574-msppj 0/1 Pending 0 37m
kube-system coredns-76f75df574-pdn7f 0/1 Pending 0 37m
kube-system etcd-ip-172-31-9-184.ec2.internal 1/1 Running 0 37m
kube-system kube-apiserver-ip-172-31-9-184.ec2.internal 1/1 Running 0 37m
kube-system kube-controller-manager-ip-172-31-9-184.ec2.internal 1/1 Running 0 37m
kube-system kube-proxy-fj4k8 1/1 Running 0 37m
kube-system kube-scheduler-ip-172-31-9-184.ec2.internal 1/1 Running 0 37m
NOTE: coredns
pods will be in “Pending” state until flannel (or other CNI) is installed.