1.启动k3s和分配端口

  • 通过Kubectl 命令来查看当前上下文:
    kubectl config current-context

  • 显示我没有设置当前上下文:error: current-context is not set

  • 查看节点信息,多次报错:
    kubectl get nodes -o wide

  • 类似:
    image

  • 配置 Kubectl 连接文件:

  • 创建 kube 配置目录
    mkdir -p ~/.kube

  • 复制 K3s 配置文件
    sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config

注:K3s 安装后会在 /etc/rancher/k3s 生成配置文件,复制到 Kubectl 默认路径

  • 修改配置文件权限
    sudo chown $(id -u):$(id -g) ~/.kube/config

  • 查看k3s服务状态:
    sudo systemctl status k3s
    发现服务已经停止了:
    image

  • 启动k3s
    sudo systemctl start k3s

  • 查看服务状态:
    sudo systemctl status k3s
    可以看到active:
    image

  • 确认6443端口监听:
    sudo ss -tunlp | grep 6443

  • 可以看到:k3s-server通过 TCP 在监听 6443 端口
    image

  • 用 kubectl 验证:
    kubectl get nodes -o wide

  • 可以看到节点已经Ready了:
    image

  • 确认3306和6379端口使用情况:
    sudo ss -tunlp | grep 3306
    sudo ss -tunlp | grep 6443

  • 我的话就是都被之前的占用的
    image

  • 有2中方法,释放或者更换端口,我选择更换端口

  • 在云服务器开启端口3307用于部署mysqk,6380用于部署redis,
    image

  • 编写Deployment + Service YAML

  • 我在我的k3s目录下:
    nano redis-hostport.yaml

点击查看代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-hostport
  labels:
    app: redis-hostport
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis-hostport
  template:
    metadata:
      labels:
        app: redis-hostport
    spec:
      containers:
      - name: redis
        image: redis:6.2.6
        ports:
        - containerPort: 6379
          hostPort: 6380    # 将容器的 6379 映射到宿主机的 6380
---
apiVersion: v1
kind: Service
metadata:
  name: redis-svc
spec:
  selector:
    app: redis-hostport
  ports:
  - port: 6380        # Service 暴露在集群内的端口
    targetPort: 6379  # 指向容器的 6379
  type: ClusterIP

  • nano mysql-hostport.yaml
点击查看代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-hostport
  labels:
    app: mysql-hostport
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql-hostport
  template:
    metadata:
      labels:
        app: mysql-hostport
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "StrongPassword123"
        ports:
        - containerPort: 3306
          hostPort: 3307    # 将容器的 3306 映射到宿主机的 3307
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-svc
spec:
  selector:
    app: mysql-hostport
  ports:
  - port: 3307        # Service 暴露在集群内的端口
    targetPort: 3306  # 指向容器的 3306
  type: ClusterIP

image

2.镜像拉取

(失败案例):
部署Redis
kubectl apply -f redis-hostport.yaml

部署MySQL
kubectl apply -f mysql-hostport.yaml
原因是:默认镜像源(Docker Hub)访问受限,因网络/DNS 被阻断而失败

  • 1.确认可用加速源
    修改为国内镜像源(和之前"Portainer 可视化面板安装"中的镜像源一样)DaoCloud
    docker pull m.daocloud.io/docker.io/library/redis:6.2.6
    docker pull m.daocloud.io/docker.io/library/mysql:8.0
    (那时我没有截图.......)

  • 2.拉取成功之后导出镜像为 tar 包,
    docker save m.daocloud.io/docker.io/library/redis:6.2.6 -o ~/redis-6.2.6.tar
    docker save m.daocloud.io/docker.io/library/mysql:8.0 -o ~/mysql-8.0.tar

  • 3.导入到 k3s 自带的 Containerd

sudo ctr --address /run/k3s/containerd/containerd.sock \
  -n k8s.io images import ~/redis-6.2.6.tar
sudo ctr --address /run/k3s/containerd/containerd.sock \
  -n k8s.io images import ~/mysql-8.0.tar

K3s 内部并不使用宿主机的 Docker,而是自带了一个独立的 containerd(监听在 /run/k3s/containerd/containerd.sock)。只有把镜像 import 到这个 containerd 中,K3s 才能"看见"并使用,否则它还是会去外网拉。结果:离线包里的镜像直接加载到 K3s 的镜像存储,跳过所有网络下载步骤。

  • 4.给镜像打"原名"标签
sudo ctr --address /run/k3s/containerd/containerd.sock \
  -n k8s.io images tag \
    m.daocloud.io/docker.io/library/redis:6.2.6 \
    docker.io/library/redis:6.2.6
sudo ctr --address /run/k3s/containerd/containerd.sock \
  -n k8s.io images tag \
    m.daocloud.io/docker.io/library/mysql:8.0 \
    docker.io/library/mysql:8.0

我的 Deployment 写的是 redis:6.2.6(等同于 docker.io/library/redis:6.2.6),如果 containerd 里只有 m.daocloud.io/docker.io/library/redis:6.2.6 这个名字,它就不会当成"原名"来匹配。Tag 操作相当于给同一份数据贴上两个标签,让 K3s 在查“docker.io/library/redis:6.2.6”时,命中本地缓存,这样镜像名与 Deployment 定义完全一致,无需修改 YAML 就能本地启动

  • 5.更新 Deployment 使用加速源镜像
kubectl set image deployment/redis-hostport \
  redis=docker.1ms.run/docker.io/library/redis:6.2.6
kubectl set image deployment/mysql-hostport \
  mysql=docker.1ms.run/docker.io/library/mysql:8.0

完成了它之后,Deployment 直接引用 m.daocloud.io/...,K3s 就不会再通过 “原名” 去拉;有时能避免 tag 步骤可能漏掉的风险

  • 6.重启和清理pod
    kubectl rollout restart deployment redis-hostport mysql-hostport
    kubectl delete pod -l 'app in (redis-hostport,mysql-hostport)'

  • 类似于这样:
    image

Kubernetes 不会自动替换掉现有的 Running/Failed Pod,rollout restart 触发新的 ReplicaSet 生成,delete pod 则强制清理掉所有旧实例和旧的 hostPort 占用,确保新 Pod 能顺利绑定宿主机端口

  • 7.等待 Pod Running
    kubectl get pods -l 'app in (redis-hostport,mysql-hostport)' -o wide
  • 我们应该可以看到如下2条Pod,READY 列变为 1/1、STATUS 变为 Running

(我mysql一条,是因为没有删除干净,它是旧 ReplicaSet 遗留的,它会一直卡在那里,消耗资源也会占用 hostPort)
我输入:kubectl delete pod mysql-hostport-855445d4fb-v4qfr就可以把它删除了,所以可以不管)
image

  • 8.验证了 MySQL 服务在 K3s 集群内的可用性,输入:
kubectl exec -it $(kubectl get pod -l app=mysql-hostport -o name) -- \
  mysql -h 127.0.0.1 -uroot -pStrongPassword123 -e "SHOW DATABASES;"

密码123

  • 结果:
    image

  • 说明MySQL 服务在容器内正常运行

  • MySQL 实例已成功初始化(包含四个系统数据库)

  • 9.验证redis服务:

kubectl exec -it \
  $(kubectl get pod -l app=redis-hostport -o name) \
  -- redis-cli ping
  • 结果
    image
  • 说明 Redis 服务已经正常启动并可连通