Docker - 部署 Kubernetes


🚀 部署 Kubernetes

Kubernetes,作为一个领先的容器编排工具,支持在各种环境中进行部署,满足不同用户的需求。


1. 🌍 部署环境

Kubernetes 支持在多种环境中部署:

  • 💻 本地主机:

    • Ubuntu
    • Debian
    • CentOS
    • Fedora
  • ☁️ 云服务:

    • 如 AWS, Azure, Google Cloud 等

2. 🛠️ 部署方式

你可以选择以下几种主流的部署方式:

  • 🟢 kubeadm:
    Kubeadm 是 Kubernetes 官方提供的用于快速部署 Kubernetes 集群的工具。它帮助你引导一个最小可行的 Kubernetes 集群,并且能够在现有的集群上进行扩展。

  • 🐳 Docker Desktop:
    对于开发者来说,Docker Desktop 是一个在本地开发环境中快速部署 Kubernetes 的简单方法。只需一键,你就可以在 Docker Desktop 中启用 Kubernetes。

  • 🌱 k3s:
    k3s 是一个轻量级的 Kubernetes 发行版,专为在资源受限的环境中运行而设计,如 IoT 设备、边缘计算等。


🎢 使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)

kubeadm 提供了一种简便的方法,通过 kubeadm initkubeadm join 命令来快速创建 Kubernetes 集群。


1. 📦 安装 containerd

首先,你需要安装 containerd

  • 为 Debian 系统:
$ sudo apt install containerd.io
  • 为 RHEL 系统:
$ sudo yum install containerd.io

2. 🛠️ 配置 containerd

接下来,需要配置 containerd。

  • 新建 /etc/systemd/system/cri-containerd.service 文件并配置相关内容。
[Unit]
Description=containerd container runtime for kubernetes
Documentation=https://containerd.io
After=network.target local-fs.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd --config //etc/cri-containerd/config.toml

Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target
  • 新建 /etc/cri-containerd/config.toml 作为 containerd 的配置文件。
version = 2
# persistent data location
root = "/var/lib/cri-containerd"
# runtime state information
state = "/run/cri-containerd"
plugin_dir = ""
disabled_plugins = []
required_plugins = []
# set containerd's OOM score
oom_score = 0

[grpc]
  address = "/run/cri-containerd/cri-containerd.sock"
  tcp_address = ""
  tcp_tls_cert = ""
  tcp_tls_key = ""
  # socket uid
  uid = 0
  # socket gid
  gid = 0
  max_recv_message_size = 16777216
  max_send_message_size = 16777216

[debug]
  address = ""
  format = "json"
  uid = 0
  gid = 0
  level = ""

[metrics]
  address = "127.0.0.1:1338"
  grpc_histogram = false

[cgroup]
  path = ""

[timeouts]
  "io.containerd.timeout.shim.cleanup" = "5s"
  "io.containerd.timeout.shim.load" = "5s"
  "io.containerd.timeout.shim.shutdown" = "3s"
  "io.containerd.timeout.task.state" = "2s"

[plugins]
  [plugins."io.containerd.gc.v1.scheduler"]
    pause_threshold = 0.02
    deletion_threshold = 0
    mutation_threshold = 100
    schedule_delay = "0s"
    startup_delay = "100ms"
  [plugins."io.containerd.grpc.v1.cri"]
    disable_tcp_service = true
    stream_server_address = "127.0.0.1"
    stream_server_port = "0"
    stream_idle_timeout = "4h0m0s"
    enable_selinux = false
    selinux_category_range = 1024
    sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5"
    stats_collect_period = 10
    # systemd_cgroup = false
    enable_tls_streaming = false
    max_container_log_line_size = 16384
    disable_cgroup = false
    disable_apparmor = false
    restrict_oom_score_adj = false
    max_concurrent_downloads = 3
    disable_proc_mount = false
    unset_seccomp_profile = ""
    tolerate_missing_hugetlb_controller = true
    disable_hugetlb_controller = true
    ignore_image_defined_volumes = false
    [plugins."io.containerd.grpc.v1.cri".containerd]
      snapshotter = "overlayfs"
      default_runtime_name = "runc"
      no_pivot = false
      disable_snapshot_annotations = false
      discard_unpacked_layers = false
      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
          runtime_type = "io.containerd.runc.v2"
          pod_annotations = []
          container_annotations = []
          privileged_without_host_devices = false
          base_runtime_spec = ""
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
            # SystemdCgroup enables systemd cgroups.
            SystemdCgroup = true
            # BinaryName is the binary name of the runc binary.
            # BinaryName = "runc"
            # BinaryName = "crun"
            # NoPivotRoot disables pivot root when creating a container.
            # NoPivotRoot = false

            # NoNewKeyring disables new keyring for the container.
            # NoNewKeyring = false

            # ShimCgroup places the shim in a cgroup.
            # ShimCgroup = ""

            # IoUid sets the I/O's pipes uid.
            # IoUid = 0

            # IoGid sets the I/O's pipes gid.
            # IoGid = 0

            # Root is the runc root directory.
            Root = ""

            # CriuPath is the criu binary path.
            # CriuPath = ""

            # CriuImagePath is the criu image path
            # CriuImagePath = ""

            # CriuWorkPath is the criu work path.
            # CriuWorkPath = ""
    [plugins."io.containerd.grpc.v1.cri".cni]
      bin_dir = "/opt/cni/bin"
      conf_dir = "/etc/cni/net.d"
      max_conf_num = 1
      conf_template = ""
    [plugins."io.containerd.grpc.v1.cri".registry]
      config_path = "/etc/cri-containerd/certs.d"
      [plugins."io.containerd.grpc.v1.cri".registry.headers]
        # Foo = ["bar"]
    [plugins."io.containerd.grpc.v1.cri".image_decryption]
      key_model = ""
    [plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
      tls_cert_file = ""
      tls_key_file = ""
  [plugins."io.containerd.internal.v1.opt"]
    path = "/opt/cri-containerd"
  [plugins."io.containerd.internal.v1.restart"]
    interval = "10s"
  [plugins."io.containerd.metadata.v1.bolt"]
    content_sharing_policy = "shared"
  [plugins."io.containerd.monitor.v1.cgroups"]
    no_prometheus = false
  [plugins."io.containerd.runtime.v2.task"]
    platforms = ["linux/amd64"]
  [plugins."io.containerd.service.v1.diff-service"]
    default = ["walking"]
  [plugins."io.containerd.snapshotter.v1.devmapper"]
    root_path = ""
    pool_name = ""
    base_image_size = ""
    async_remove = false

3. 🚀 安装 kubelet, kubeadm, kubectl, cri-tools, kubernetes-cni

  • 对于 Ubuntu/Debian:
# 添加源并安装
$ apt-get update && apt-get install -y apt-transport-https
$ curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -

$ cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF

$ apt-get update
$ apt-get install -y kubelet kubeadm kubectl
  • 对于 CentOS/Fedora:
# 添加源并安装
$ cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

$ sudo yum install -y kubelet kubeadm kubectl

4. ⚙️ 修改内核的运行参数

执行以下命令来修改内核的运行参数。

$ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# 应用配置
$ sysctl --system

5. 🛠️ 配置 kubelet

要配置 kubelet,你需要修改 kubelet.service 文件。具体步骤如下:

1. 📝 修改 kubelet.service 文件

/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf 路径下创建或修改文件,加入以下内容:

# 启用 ipvs 相关内核模块
[Service]
ExecStartPre=-/sbin/modprobe ip_vs
ExecStartPre=-/sbin/modprobe ip_vs_rr
ExecStartPre=-/sbin/modprobe ip_vs_wrr
ExecStartPre=-/sbin/modprobe ip_vs_sh

这些命令将在 kubelet 服务启动之前加载 ipvs 相关的内核模块。

2. 🔄 应用配置

为了使这些更改生效,你需要重新加载 systemd 的配置。执行以下命令:

$ sudo systemctl daemon-reload

这条命令会使 systemd 重新读取修改后的配置文件。


6. 🚀 部署


🖥️ Master 节点部署

  1. 启用 cri-containerd 服务:

    $ systemctl enable cri-containerd
    
  2. 启动 cri-containerd 服务:

    $ systemctl start cri-containerd
    
  3. 初始化 Kubernetes:

    使用 kubeadm 初始化 Kubernetes 集群:

    $ sudo kubeadm init \
          --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
          --pod-network-cidr 10.244.0.0/16 \
          --cri-socket /run/cri-containerd/cri-containerd.sock \
          --v 5 \
          --ignore-preflight-errors=all
    

    注意: --pod-network-cidr 10.244.0.0/16 参数与后续 CNI 插件有关。这里以 flannel 为例。如果你打算部署其他类型的网络插件,请更改此参数。

    在执行过程中,可能会出现错误,例如缺少依赖包。如果有提示,请根据提示安装相应的包。

    执行成功后, 你会看到以下输出:

    ...
    [addons] Applied essential addon: CoreDNS
    [addons] Applied essential addon: kube-proxy
    ...
    

    这意味着你的 Kubernetes 控制平面已成功初始化!

  4. 开始使用集群:

    为了开始使用你的集群,你需要执行以下操作:

    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
    

    接下来, 你应该为集群部署一个 pod 网络。


🖥️ Node (工作节点) 部署

如果你有其他机器希望加入到这个集群作为工作节点, 请按照以下步骤进行:

  1. 在另一台机器上重复 “Master 节点部署” 的前两个步骤。

  2. 加入集群:

    根据主节点的提示,加入到集群:

    $ kubeadm join 192.168.199.100:6443 \
        --token cz81zt.orsy9gm9v649e5lf \
        --discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe \
        --cri-socket /run/cri-containerd/cri-containerd.sock
    

    这样, 你的工作节点就成功地加入了 Kubernetes 集群!


7. 🌐 查看服务


🛠️ 查看运行的容器

首先, 我们可以通过 crictl 工具查看实际运行的容器:

CONTAINER_RUNTIME_ENDPOINT=/run/cri-containerd/cri-containerd.sock crictl ps -a

📋 服务分类

1. 主节点服务 (Master Node Services)

🔹 apiserver
- 描述: 是整个系统的对外接口。
- 功能: 提供 RESTful 的方式供客户端和其它组件调用。

# 查看 apiserver 的状态和日志
kubectl get pods -n kube-system | grep apiserver
kubectl logs -n kube-system <apiserver-pod-name>

🔹 scheduler
- 描述: 负责资源的调度。
- 功能: 根据需要,分配某个 pod 到某个节点上。

# 查看 scheduler 的状态和日志
kubectl get pods -n kube-system | grep scheduler
kubectl logs -n kube-system <scheduler-pod-name>

🔹 controller-manager
- 描述: 负责管理各种控制器。
- 功能:
- endpoint-controller: 刷新服务和 pod 的关联信息。
- replication-controller: 维护某个 pod 的副本数量为配置的数值。

# 查看 controller-manager 的状态和日志
kubectl get pods -n kube-system | grep controller-manager
kubectl logs -n kube-system <controller-manager-pod-name>

2. 工作节点服务 (Worker Node Services)

🔹 proxy
- 描述: 为 pod 上的服务提供访问的代理。

# 查看 proxy 的状态和日志
kubectl get pods -n kube-system | grep proxy
kubectl logs -n kube-system <proxy-pod-name>

3. 其它服务

🔹 Etcd
- 描述: 是所有 Kubernetes 状态的存储数据库。

# 查看 etcd 的状态和日志
kubectl get pods -n kube-system | grep etcd
kubectl logs -n kube-system <etcd-pod-name>

8. 📡 部署 CNI

  • 选择一个 CNI 插件并部署。这里以 flannel 为例。

🔧 配置 kubectl

首先,将 Kubernetes 集群的配置文件复制到 ~/.kube/config,这样可以方便地使用 kubectl 命令与集群进行交互。使用以下命令来复制配置文件:

sudo cp -i /etc/kubernetes/admin.conf ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config

👀 查看已部署的服务

使用以下命令可以查看已经部署的服务和应用:

kubectl get all -A

这会列出所有的资源,包括 pods、services、deployments 等等。可以通过这些资源来管理和监控集群中的应用程序。

🌐 部署网络插件 (CNI 插件)

  • 检查 podCIDR 设置

    $ kubectl get node -o yaml | grep CIDR
    
    # 输出
        podCIDR: 10.244.0.0/16
        podCIDRs:
    
  • Kubernetes 集群需要网络插件来使不同的 Pod 之间可以互相通信。一种常见的网络插件是 Flannel。可以使用以下步骤来部署 Flannel 网络插件:

    kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.11.0/Documentation/kube-flannel.yml
    
  • 请注意,如果您使用的是单节点集群(例如使用 kubeadm 部署的),默认情况下,主节点不会运行 pod。您可以使用以下命令来解除此限制:

    kubectl taint nodes --all node-role.kubernetes.io/master-
    

    这会允许主节点运行 pod。


9. 📚 参考文档


☁️ Docker Desktop

在 Docker Desktop 上使用 Kubernetes 可以提供便捷的本地 Kubernetes 集群。以下是在 Docker Desktop 上启用和测试 Kubernetes 的步骤:


⚡️ 获取 k8s.gcr.io 镜像

由于国内拉取不到 k8s.gcr.io 镜像,我们可以使用开源项目 AliyunContainerService/k8s-for-docker-desktop 来获取所需的镜像。


🏁 启用 Kubernetes

  1. 打开 Docker Desktop 应用程序。

  2. 点击菜单栏中的 Docker 图标,选择 “Preferences”(首选项)。

  3. 在首选项窗口中,选择 “Kubernetes” 选项卡。

  4. 勾选 “Enable Kubernetes” 复选框。

  5. 点击 “Apply & Restart”(应用并重启)按钮。Docker Desktop 将会开始启动 Kubernetes 集群。

  6. 等待一段时间,直到状态栏中的 “Kubernetes is running”(Kubernetes 运行中)消息出现。这表示 Kubernetes 集群已成功启动。

在这里插入图片描述


🧪 测试 Kubernetes

  1. 打开终端(命令行界面)。

  2. 运行以下命令来检查 Kubernetes 的版本信息:

    kubectl version
    

    如果成功输出版本信息,则表示 Kubernetes 已经在 Docker Desktop 上启用并运行。

现在,您已经成功在 Docker Desktop 上启用了 Kubernetes,并可以开始使用 Kubernetes 集群进行本地开发和测试。您可以使用 kubectl 命令管理和操作 Kubernetes 资源,以及部署和运行容器化应用程序。


🧲 部署 kubernetes 集群


🎉 部署 Kubernetes Dashboard

  • 官方文档

  • Kubernetes Dashboard 是一个基于 Web 的 Kubernetes 用户界面,用于可视化地管理和监视 Kubernetes 集群。以下是在 Kubernetes 集群上部署和访问 Kubernetes Dashboard 的步骤:

在这里插入图片描述


🚀 部署 Kubernetes Dashboard

执行以下命令即可部署 Kubernetes Dashboard:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml

这将创建 Kubernetes Dashboard 所需的所有资源。


🌐 访问 Kubernetes Dashboard

要访问 Kubernetes Dashboard,请执行以下步骤:

  1. 打开终端,并运行以下命令来启动代理:

    kubectl proxy
    

    这将在本地主机的 8001 端口上启动一个代理,允许您通过代理访问 Kubernetes API。

  2. 在浏览器中打开以下 URL 以访问 Kubernetes Dashboard:

    http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
    

    请注意,此 URL 是通过代理访问 Kubernetes Dashboard 的地址。


🔑 登录 Kubernetes Dashboard

Kubernetes Dashboard 目前仅支持使用 Bearer 令牌进行身份验证。以下是如何创建并使用 Bearer 令牌登录的步骤:

  1. 创建一个名为 dashboard-admin 的 ServiceAccount 和 ClusterRoleBinding,授予其集群管理员角色。执行以下命令:

    kubectl create sa dashboard-admin -n kube-system
    kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
    
  2. 获取 dashboard-admin ServiceAccount 的令牌并保存到环境变量中。执行以下命令:

    ADMIN_SECRET=$(kubectl get secrets -n kube-system | grep dashboard-admin | awk '{print $1}')
    DASHBOARD_LOGIN_TOKEN=$(kubectl describe secret -n kube-system ${ADMIN_SECRET} | grep -E '^token' | awk '{print $2}')
    
  3. 打印出 DASHBOARD_LOGIN_TOKEN 的值:

    echo ${DASHBOARD_LOGIN_TOKEN}
    
  4. DASHBOARD_LOGIN_TOKEN 的值粘贴到 Kubernetes Dashboard 登录页面,即可成功登录。

现在,您已经成功部署和访问了 Kubernetes Dashboard,并可以使用该界面来管理和监视您的 Kubernetes 集群。请妥善保管令牌,以确保安全性。


💚 Kubernetes 命令行工具

Kubernetes 命令行工具 kubectl 是与 Kubernetes 集群进行交互的主要工具。以下是一些常用 kubectl 命令及其功能的详解:


  1. get: 用于显示一个或多个资源的信息。示例:

    kubectl get pods            # 获取所有 Pods 的列表
    kubectl get services        # 获取所有 Services 的列表
    
  2. describe: 用于显示资源的详细信息。示例:

    kubectl describe pod <pod-name>     # 获取特定 Pod 的详细信息
    
  3. create: 用于从文件或标准输入创建资源。示例:

    kubectl create -f pod.yaml         # 从 YAML 文件创建一个 Pod
    
  4. update: 用于从文件或标准输入更新资源。示例:

    kubectl apply -f pod-updated.yaml  # 从更新后的 YAML 文件更新一个 Pod
    
  5. delete: 用于删除资源。可以通过文件名、标准输入、资源名或者 label selector 删除资源。示例:

    kubectl delete pod <pod-name>      # 删除特定 Pod
    
  6. log: 用于查看 Pod 中一个容器的日志。示例:

    kubectl logs <pod-name> -c <container-name>   # 查看特定容器的日志
    
  7. exec: 用于在容器内部执行命令。示例:

    kubectl exec -it <pod-name> -- /bin/bash     # 进入容器的命令行终端
    
  8. port-forward: 用于将本地端口转发到 Pod。示例:

    kubectl port-forward <pod-name> 8080:80     # 将本地 8080 端口映射到 Pod 的 80 端口
    
  9. proxy: 用于为 Kubernetes API server 启动代理服务器,以便访问集群内部资源。示例:

    kubectl proxy     # 启动代理服务器,允许通过 API 访问集群资源
    
  10. run: 用于在集群中使用指定镜像启动容器。示例:

    kubectl run nginx --image=nginx     # 启动一个名为 "nginx" 的容器
    
  11. expose: 用于将 replication controller、service 或 pod 暴露为新的 Kubernetes service。示例:

    kubectl expose deployment my-deployment --type=NodePort --port=80     # 将 Deployment 暴露为 NodePort 服务
    
  12. label: 用于更新资源的 label,以便对资源进行分类和选择。示例:

    kubectl label pod <pod-name> app=backend     # 为 Pod 添加一个标签
    
  13. config: 用于修改 Kubernetes 配置文件。示例:

    kubectl config view     # 查看当前配置文件内容
    
  14. cluster-info: 用于显示集群信息,包括 API server 地址等。示例:

    kubectl cluster-info     # 显示集群信息
    
  15. api-versions: 以 “组/版本” 的格式输出服务端支持的 API 版本。示例:

    kubectl api-versions     # 列出支持的 API 版本
    
  16. version: 输出服务端和客户端的版本信息。示例:

    kubectl version     # 查看 Kubernetes 服务端和客户端版本信息
    
  17. help: 显示各个命令的帮助信息。示例:

    kubectl get --help     # 查看 `get` 命令的帮助信息
    

这些是 kubectl 常用命令及其功能的简要介绍。kubectl 是 Kubernetes 管理和操作的重要工具,您可以根据需要使用不同的命令来管理 Kubernetes 集群。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yueerba126

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值