Skip to content

Part 1: Guide to Creating an Offline Installation Package for Kubernetes v1.33.13 (Online Environment Edition) ​

vCenter Server 8.0 installation and deployment diagram

Applicable Scenarios and Prerequisites ​

projectExplanation
Applicable scenariosTo deploy Kubernetes in an intranet or fully disconnected production environment, you need to prepare a complete offline installation package in advance in a networked environment.
Operate the machineA device that can access the Internet Ubuntu 22.04 A machine (which can be a personal computer, cloud server, or virtual machine).
Kubernetes versionv1.33.13
Container runtimecontainerd (version >= 1.7.25)
Network pluginCalico v3.26.0

Goal of the First Article ​

at Network available complete all the following operations on the machine, and finally package and generate a k8s-offline-v1.33.13.tar.gz Offline installation package:

k8s-offline-v1.33.13.tar.gz
├── deb-packages/
│   ├── kubernetes/                 # kubeadm, kubelet, kubectl and their dependencies
│   └── cri/                        # containerd.io, runc, and their dependencies
├── images/
│   ├── k8s-images.tar              # Kubernetes core images
│   ├── calico-images.tar           # Calico network plugin image
│   ├── dashboard-images.tar        # Kubernetes Dashboard image
│   └── base-images.tar             # Common base images (busybox, nginx, alpine)
├── manifests/
│   ├── calico.yaml                 # Calico network plugin configuration file
│   └── kubernetes-dashboard.yaml   # Kubernetes Dashboard deployment configuration file
└── install.sh                      # Offline environment one-click installation script

1. Preparatory Work (Online Environment Machine) ​

1.1 Operating System Environment Check ​

Ensure your Ubuntu 22.04 system meets the following basic requirements:

bash
# Check the operating system version
lsb_release -a

# Check the kernel version (5.15+ recommended)
uname -r

# Check disk space (at least 5GB of free space required)
df -h /

1.2 Operate as a regular user ​

[!important] Important Notice During the offline package creation process, it is recommended to use Regular user(rather than root) to perform operations, avoid apt-get download Permission warning appears:

W: Download is performed unsandboxed as root as file
bash
# If the current user is root, switch to a regular user (e.g., testify)
su - testify

# Confirm the current user
whoami

1.3 Create Working Directory ​

bash
# Create the offline package root directory
mkdir -p ~/k8s-offline/v1.33.13
cd ~/k8s-offline/v1.33.13

# Create subdirectory
mkdir -p deb-packages/kubernetes deb-packages/cri images manifests

1.4 Configure apt proxy (if network is restricted) ​

If your network environment requires a proxy to access the external network, please configure it first apt Agent:

bash
# Check whether the proxy is available (please replace with the actual proxy address)
curl -I -x http://192.168.0.23:7890 https://google.com

# Configure persistent proxy (optional)
sudo tee /etc/apt/apt.conf.d/99proxy.conf <<EOF
Acquire::http::proxy "http://192.168.0.23:7890";
Acquire::https::proxy "http://192.168.0.23:7890";
EOF

# Update apt cache
sudo apt-get update

1.5 Configure shell proxy environment variables ​

Except for apt Besides needing to configure a proxy,curl,wget、docker Commands such as these also need to access the external network through a proxy. It is recommended to configure the shell proxy environment variables uniformly.

Method 1: Temporarily effective (current session only) ​

bash
export http_proxy=http://192.168.0.23:7890
export https_proxy=http://192.168.0.23:7890
export no_proxy=localhost,127.0.0.1,.local,.aliyuncs.com

Write the proxy configuration into ~/.bashrc, automatically loaded on each login:

bash
# Use tee to append the proxy configuration to ~/.bashrc
tee -a ~/.bashrc <<'EOF'

# ============================================
# Proxy configuration (please replace with the actual proxy address)
# ============================================
export http_proxy=http://192.168.0.23:7890
export https_proxy=http://192.168.0.23:7890
export no_proxy=localhost,127.0.0.1,.local,.aliyuncs.com
EOF

# Make the configuration take effect immediately
source ~/.bashrc

[!tip] Why use tee -a?

  • tee -a Can Add The content is appended to the end of the file and will not overwrite existing configuration.

  • cooperate <<'EOF' Variables can be kept as-is (without expansion), and the written content must be exactly the same as in the code block.

  • Compared to echo >>,tee Supports writing with sudo privileges, making it more flexible and secure.

Verify whether the proxy configuration takes effect ​

bash
# Check the current proxy environment variables
env | grep -i proxy

# Test proxy connectivity
curl -I https://www.google.com
# Or test with wget
wget --spider https://www.google.com

The expected output should include:

http_proxy=http://192.168.0.23:7890
https_proxy=http://192.168.0.23:7890
no_proxy=localhost,127.0.0.1,.local,.aliyuncs.com

[!warning] Precautions

  • Please replace the proxy address.: will 192.168.0.23:7890 Replace with the actual proxy server address and port available to you.

  • no_proxy configuration: It is recommended to use the intranet domain name (e.g..aliyuncs.com) Join no_proxy, to avoid slow speeds caused by using a proxy when pulling domestic mirrors.

  • sudo command proxy is invalid: Use sudo When executing commands, environment variables may not be inherited. If you need sudo to also use the proxy, you can use sudo -E Keep the current environment variables, or in /etc/environment Configure the system-level proxy in.

1.6 Configure Docker daemon proxy (Important!) ​

[!important] Why does it need to be configured separately? Docker uses a C/S architecture,daemon process(dockerd) is responsible for pulling the image, but it Do not read proxy configuration in shell environment variables. Therefore, even if configured ~/.bashrc,docker pull It may still fail due to timeout.

Configuration steps:

bash
# 1. Create Docker service configuration directory
sudo mkdir -p /etc/systemd/system/docker.service.d

# 2. Write proxy configuration
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://192.168.0.23:7890"
Environment="HTTPS_PROXY=http://192.168.0.23:7890"
Environment="NO_PROXY=localhost,127.0.0.1,.local,.aliyuncs.com"
EOF

After configuration is complete,docker pull Then you can pull the image normally.

[!warning] Pitfall warning: NO_PROXY should not include .docker.io

When configuring the Docker daemon proxy,Never take .docker.io or registry-1.docker.io Join NO_PROXY, otherwise Docker Hub traffic will not go through the proxy, causing failures when pulling images such as Calico.

✅ Correct example:

bash
Environment="NO_PROXY=localhost,127.0.0.1,.local,.aliyuncs.com"

❌ Incorrect example (will cause Calico pull failure):

bash
Environment="NO_PROXY=localhost,127.0.0.1,.local,.aliyuncs.com,.docker.io"

1.7 Install necessary tools ​

bash
sudo apt-get update
sudo apt-get install -y apt-transport-https curl gnupg wget

II. Create an offline package for Kubernetes components ​

2.1 Add Kubernetes apt repository ​

bash
# 1. Create the keyrings directory
sudo mkdir -p /etc/apt/keyrings

# 2. Download and add the GPG key
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# 3. Add the Kubernetes apt source
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 4. Update the apt cache
sudo apt-get update

2.2 Download Kubernetes components and their dependencies ​

bash
# Switch to the Kubernetes deb package directory
cd ~/k8s-offline/v1.33.13/deb-packages/kubernetes

# Download core components (specified version)
apt-get download \
  kubelet=1.33.13-1.1 \
  kubeadm=1.33.13-1.1 \
  kubectl=1.33.13-1.1

# Download dependency packages
apt-get download \
  conntrack \
  ebtables \
  socat \
  ethtool \
  ipset \
  nfs-common \
  libseccomp2 \
  libltdl7 \
  libnfsidmap1 \
  libipset13 \
  libtirpc3 \
  libtirpc-common \
  rpcbind \
  keyutils \
  cri-tools \
  kubernetes-cni

# View download results
ls -lh

[!tip] If the download fails If you encounter Could not handshake and other network errors, please check whether the proxy configuration is correct (refer to 1.4 Section).

III. Create an offline package for the container runtime (containerd) ​

[!warning] Version requirements Kubernetes v1.33.13 requires containerd version >= 1.7.25, while the official Ubuntu 22.04 repository by default only provides 1.7.12. Therefore, we need to use the latest version provided by the official Docker repository containerd.io.

3.1 Add the official Docker apt repository ​

bash
# 1. Add the official Docker GPG key
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 2. Add Docker apt repository (compatible with Ubuntu 22.04 jammy)
sudo echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu jammy stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 3. Update cache
sudo apt-get update

3.2 Download containerd.io and dependencies ​

bash
# Switch to the CRI deb package directory
cd ~/k8s-offline/v1.33.13/deb-packages/cri

# Can be viewed by checking the available versions
apt-cache madison containerd.io

# Download containerd.io (version 2.3.3-1~ubuntu.22.04~jammy)
apt-get download containerd.io=2.3.3-1~ubuntu.22.04~jammy

# View download results
ls -lh

IV. Create an Offline Package for Container Images ​

4.1 Install kubeadm (used to obtain the image list) ​

bash
# Install kubeadm (temporary installation only on the current build machine)
sudo apt-get install -y kubelet=1.33.13-1.1 kubeadm=1.33.13-1.1 kubectl=1.33.13-1.1
sudo apt-mark hold kubelet kubeadm kubectl

4.2 Install Docker (for pulling and saving images) ​

bash
# Install Docker
sudo apt-get install -y docker.io

# Start the Docker service
sudo systemctl daemon-reload
sudo systemctl start docker
sudo systemctl enable docker

# Verify configuration 1.6 Configure Docker daemon proxy
sudo systemctl show --property=Environment docker

# Verify Docker installation
sudo docker version

4.3 Pull Kubernetes v1.33.13 Core Images ​

bash
# View the list of images required for Kubernetes v1.33.13
sudo kubeadm config images list --kubernetes-version=v1.33.13

Output example:

registry.k8s.io/kube-apiserver:v1.33.13
registry.k8s.io/kube-controller-manager:v1.33.13
registry.k8s.io/kube-scheduler:v1.33.13
registry.k8s.io/kube-proxy:v1.33.13
registry.k8s.io/coredns/coredns:v1.12.0
registry.k8s.io/pause:3.10
registry.k8s.io/etcd:3.5.24-0
bash
# Pull all images
images=(
  registry.k8s.io/kube-apiserver:v1.33.13
  registry.k8s.io/kube-controller-manager:v1.33.13
  registry.k8s.io/kube-scheduler:v1.33.13
  registry.k8s.io/kube-proxy:v1.33.13
  registry.k8s.io/coredns/coredns:v1.12.0
  registry.k8s.io/pause:3.10
  registry.k8s.io/etcd:3.5.24-0
)

for image in "${images[@]}"; do
  sudo docker pull $image
done

4.4 Export Kubernetes core images as tar files ​

bash
cd ~/k8s-offline/v1.33.13/images

sudo docker save -o k8s-images.tar \
  registry.k8s.io/kube-apiserver:v1.33.13 \
  registry.k8s.io/kube-controller-manager:v1.33.13 \
  registry.k8s.io/kube-scheduler:v1.33.13 \
  registry.k8s.io/kube-proxy:v1.33.13 \
  registry.k8s.io/coredns/coredns:v1.12.0 \
  registry.k8s.io/pause:3.10 \
  registry.k8s.io/etcd:3.5.24-0

# Check the size of the exported file
ls -lh k8s-images.tar

4.5 Pull and export Calico network plugin images ​

bash
# Pull the Calico v3.26.0 image
images=(
  docker.io/calico/node:v3.30.6
  docker.io/calico/cni:v3.30.6
  docker.io/calico/kube-controllers:v3.30.6
)

for image in "${images[@]}"; do
  sudo docker pull $image
done

# Export Calico images
sudo docker save -o calico-images.tar \
  docker.io/calico/node:v3.30.6 \
  docker.io/calico/cni:v3.30.6 \
  docker.io/calico/kube-controllers:v3.30.6

# Check the size of the exported file
ls -lh calico-images.tar

4.6 Pull and export the Kubernetes Dashboard image (optional) ​

[!tip] Optional component Kubernetes Dashboard is the official Web UI management interface, making it convenient to view and manage cluster resources graphically. If you do not need the Web UI, you can skip this section.

Pull the Dashboard image:

bash
# Pull the Kubernetes Dashboard v2.7.0 image.
images=(
  kubernetesui/dashboard:v2.7.0
  kubernetesui/metrics-scraper:v1.0.8
)

for image in "${images[@]}"; do
  sudo docker pull $image
done

Export the Dashboard image as a tar file:

bash
cd ~/k8s-offline/v1.33.13/images

sudo docker save -o dashboard-images.tar \
  kubernetesui/dashboard:v2.7.0 \
  kubernetesui/metrics-scraper:v1.0.8

# Check the size of the exported file
ls -lh dashboard-images.tar

4.7 Pull and export commonly used base images (optional) ​

[!tip] Optional components These base images are used for functional verification after Kubernetes cluster deployment and for daily operations and maintenance debugging. It is strongly recommended to include them to facilitate subsequent cluster verification and troubleshooting.

Pull commonly used base images:

bash
# Pull commonly used base images
images=(
  busybox:1.36.1
  nginx:1.31.3
  alpine:3.18
)

for image in "${images[@]}"; do
  sudo docker pull $image
done

Export the base image as a tar file:

bash
cd ~/k8s-offline/v1.33.13/images

sudo docker save -o base-images.tar \
  busybox:1.36.1 \
  nginx:1.31.3 \
  alpine:3.18

# Check the size of the exported file
ls -lh base-images.tar

4.8 Modify Image Owner ​

bash
# Change the owner of all files in the images directory to the current user
sudo chown -R $(whoami):$(whoami) ~/k8s-offline/v1.33.13/images/

💡 Note

To make it convenient for the current user to ultimately package the offline package, it is necessary to change its ownership to that of the current user.

V. Download the Kubernetes add-on configuration file ​

This step downloads the configuration files for the cluster network plugin Calico and the optional Web UI Kubernetes Dashboard for use in offline environments.

1. Download the Calico network plugin configuration file

bash
cd ~/k8s-offline/v1.33.13/manifests

# Download Calico v3.30.6 configuration file
wget -c https://raw.githubusercontent.com/projectcalico/calico/v3.30.6/manifests/calico.yaml -O calico.yaml

# Verify that the file download was successful
head -n 5 calico.yaml

2. Download the Kubernetes Dashboard deployment configuration file (optional)

[!tip] Optional components If you do not need the Dashboard Web UI, you can skip this step.

bash
cd ~/k8s-offline/v1.33.13/manifests

# Download Kubernetes Dashboard v2.7.0 deployment manifest
wget -c https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml -O kubernetes-dashboard.yaml

# Verify that the file download was successful
head -n 5 kubernetes-dashboard.yaml

[!warning] About the Dashboard image Required for Dashboard kubernetesui/dashboard:v2.7.0 and kubernetesui/metrics-scraper:v1.0.8 The image is already at Section 4.6 Pull and export from it. This step only downloads the deployment manifest; the images and manifest will be used together in an offline environment.

6. Write an offline installation script ​

bash
cd ~/k8s-offline/v1.33.13

cat > install.sh << 'EOF'
#!/bin/bash

set -e

echo "========================================="
echo "  Kubernetes v1.33.13 Offline Installation Script"
echo "  Suitable for Ubuntu 22.04 + containerd"
echo "========================================="

# 1. Install Kubernetes components
echo "[1/8] Installing Kubernetes components..."
sudo dpkg -i ./deb-packages/kubernetes/*.deb

# 2. Install the containerd runtime
echo "[2/8] Installing containerd runtime..."
sudo dpkg -i ./deb-packages/cri/*.deb

# 3. Start the containerd service
echo "[3/8] Starting containerd service..."
sudo systemctl enable containerd
sudo systemctl start containerd

# 4. Load Kubernetes images into containerd
echo "[4/8] Loading Kubernetes images..."
sudo ctr -n=k8s.io images import ./images/k8s-images.tar

# 5. Load Calico images into containerd
echo "[5/8] Loading Calico images..."
sudo ctr -n=k8s.io images import ./images/calico-images.tar

# 6. Load the Dashboard image into containerd (optional)
if [ -f ./images/dashboard-images.tar ]; then
  echo "[6/8] Loading Dashboard image..."
  sudo ctr -n=k8s.io images import ./images/dashboard-images.tar
else
  echo "[6/8] Skipping Dashboard image (file does not exist)..."
fi

# 7. Load the base image into containerd (optional)
if [ -f ./images/base-images.tar ]; then
  echo "[7/8] Loading base image..."
  sudo ctr -n=k8s.io images import ./images/base-images.tar
else
  echo "[7/8] Skipping base image (file does not exist)..."
fi

# 8. Lock the Kubernetes version (prevent automatic upgrades)
echo "[8/8] Locking Kubernetes version..."
sudo apt-mark hold kubelet kubeadm kubectl

echo "========================================="
echo "  All components installed successfully!"
echo "  Next, please execute in order:"
echo "  1. Configure containerd (reference documentation)"
echo "  2. kubeadm init initialize the cluster"
echo "  3. Deploy Dashboard (if needed)"
echo "========================================="
EOF

# Add executable permission
chmod +x install.sh

VII. Production Checklist (Optional) ​

Before packaging, it is recommended to generate a file list in the offline package directory to facilitate subsequent verification. This list will also be included in the final archive.

bash
# Enter the offline package root directory.
cd ~/k8s-offline/v1.33.13

# Generate the manifest file in the current directory
cat > manifest.txt <<EOF
========================================
Kubernetes v1.33.13 offline installation package list
Generation time: $(date)
========================================

1. Deb packages (deb-packages/)

Kubernetes components (deb-packages/kubernetes/):
$(ls -1 deb-packages/kubernetes/)

containerd component (deb-packages/cri/):
$(ls -1 deb-packages/cri/)

II. Container Images (images/)
$(ls -lh images/*.tar | awk '{print $9, $5}')

III. Configuration Files (manifests/)
$(ls -1 manifests/)

IV. Installation Script
install.sh

========================================
EOF

# View the contents of the generated list
cat manifest.txt

8. Package all offline resources ​

At this moment,v1.33.13 The directory already contains all offline resource files and the newly generated manifest.txt Manifest files can be packaged together.

bash
cd ~/k8s-offline

# Package (using regular user permissions); note that the source path is the v1.33.13 directory, and the final directory in the tar package has been renamed.
tar -zcvf k8s-offline-v1.33.13.tar.gz --transform='s/v1.33.13/k8s-offline-v1.33.13/' ./v1.33.13

# View packaging results
ls -lh k8s-offline-v1.33.13.tar.gz

[!tip] Tip The packaged file is usually about 665 MB, and the exact size depends on the number of images included. The archive now includes a manifest file.

9. Transfer the offline package to the target server ​

will k8s-offline-v1.33.13.tar.gz Transfer to all three intranet servers (master, node1, node2):

bash
# Example: Use scp to transfer to all nodes
scp k8s-offline-v1.33.13.tar.gz [email protected]:/tmp/
scp k8s-offline-v1.33.13.tar.gz [email protected]:/tmp/
scp k8s-offline-v1.33.13.tar.gz [email protected]:/tmp/

[!tip] Tip If the file is large, consider using a USB flash drive, intranet shared storage, or other high-speed transfer methods.

Appendix: Frequently Asked Questions ​

Q1: apt-get download error "Unable to locate package" ​

Reason: The corresponding apt source was not added correctly or was not executed.apt-get update.

Solve: Check /etc/apt/sources.list.d/ whether the corresponding source file exists in the directory, and execute it sudo apt-get update.

Q2: docker pull image failed ​

Reason Docker daemon is not correctly configured with a proxy, or the proxy address is unavailable.

Solve:

  • Check whether the Docker daemon proxy configuration in Section 1.6 is correct

  • Verify whether the proxy is available:curl -I -x http://your-proxy:port https://www.google.com

  • Restart Docker service:sudo systemctl daemon-reload && sudo systemctl restart docker

  • Check Docker daemon environment variables:sudo systemctl show --property=Environment docker

  • Confirm in NO_PROXY No Include .docker.io(Refer to Section 1.6 for tips on avoiding common pitfalls)

Q3: The packaged file is too large ​

reason The image file is relatively large.

Solve: Under normal circumstances, the image tar package is about 665 MB, which is within the normal range. If space is insufficient, consider cleaning up unnecessary images or using a packaging method with a higher compression ratio (e.g.,xz).

Next post preview ​

《Kubernetes v1.33.13 Three-Node Cluster Offline Installation Guide (Internal Network Environment Edition)》 will include:

  • Prerequisite preparation for three servers (static IP, hostname, mutual connectivity via /etc/hosts, disabling the firewall, disabling swap, loading necessary kernel modules, configuring kernel parameters, etc.)

  • Extract the offline installation package and run the installation script.

  • containerd Configuration and Sandbox Image Correction

  • kubeadm initialize the control plane

  • Calico Network Plugin Installation

  • Worker nodes join the cluster

  • Comprehensive verification of cluster status

📌This concludes Part One. All commands have been verified in the Ubuntu 22.04 environment. Please execute them in order to ensure the offline package is created successfully. If you have any questions, please refer to the FAQ section in the documentation.

Attachment: Resource Download ​

If you do not want to create an offline package yourself, you can directly download a ready-made complete offline resource package, which includes all the content described in this document.deb packages, container images, configuration files, and installation scripts.

ResourcesDownload linkExplanation
offline package filek8s-offline-v1.33.13-20260823-1241.tar.gzKubernetes v1.33.13 complete offline resource package, approximately 665 MB
SHA256 checksumk8s-offline-v1.33.13-20260823-1241.tar.gz.sha256Used to verify the integrity of offline packages and ensure files are not corrupted

[!tip] Usage tips

  • After downloading the offline package, it is recommended to first use sha256sum -c k8s-offline-v1.33.13-20260823-1241.tar.gz.sha256 Verify file integrity.

  • Transfer the archive to the target intranet server's /opt/ Under the directory, then deploy by following the steps in Part 2, "Intranet Installation Guide."

Last updated on11/07/2026, 02:16 PM
@fishfinal | @fishfinals | [email protected]