WSL2 安装

WSL2 安装步骤与 《WSL2+KinD部署K8S》一样;

配置 Linux

禁用 swap

因为 kubelet 不支持 swap 内存,因此需要通过设置 wslconfig 禁用 swap。在 用户根目录 创建 .wslconfig 文件,例如: ‘C:\Users\xiong’ ,添加以下内容:

  1. [wsl2]
  2. swap=0 # 关闭swap
  3. [network]
  4. generateResolvConf = false # 解决域名解析失败的问题

然后在 powershell 或 cmd 运行以下命令,关闭 wsl,再点击开始菜单 Ubuntu 图标,即完成重启 WSL。

wsl --shutdown

设置 /etc/resolve.conf

因为每次 WSL 启动会自动覆盖 /etc/resolve.conf 文件,可能会导致域名解析失败的问题,必要时可以设置自定义的 DNS服务器 ,把以下内容追加到 /etc/resolve.conf 文件末尾:(需要 root 权限,记得加上 sudo)

nameserver 8.8.8.8
nameserver 114.114.114.114

替换 apt 源

root@k8s:~# cp /etc/apt/sources.list /etc/apt/sources.list.bak
root@k8s:~# echo "deb http://mirrors.aliyun.com/ubuntu/ focal main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal universe
deb http://mirrors.aliyun.com/ubuntu/ focal-updates universe
deb http://mirrors.aliyun.com/ubuntu/ focal multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal-security universe
deb http://mirrors.aliyun.com/ubuntu/ focal-security multiverse" > /etc/apt/sources.list
root@k8s:~#

然后执行更新即可:

root@k8s:~# apt update && apt upgrade -y

配置 Systemd

由于默认情况下 WSL 中不能使用 systemd,所以很多应用程序没办法启动,不过还是有一些大神解决了这个问题,我们可以在 https://forum.snapcraft.io/t/running-snaps-on-wsl2-insiders-only-for-now/13033 链接下面找到启动 SystemD 的方法。
首先安装 Systemd 相关的依赖应用:

apt install -yqq fontconfig daemonize

然后创建一个如下所示的脚本文件:

# Create the starting script for SystemD
vi /etc/profile.d/00-wsl2-systemd.sh
SYSTEMD_PID=$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')

if [ -z "$SYSTEMD_PID" ]; then
   sudo /usr/bin/daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
   SYSTEMD_PID=$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')
fi

if [ -n "$SYSTEMD_PID" ] && [ "$SYSTEMD_PID" != "1" ]; then
    exec sudo /usr/bin/nsenter -t $SYSTEMD_PID -a su - $LOGNAME
fi

上面的脚本放置在 /etc/profile.d 目录下面,所以要让脚本生效,我们需要退出当前 session,重新进入即可。

安装 Docker

移除旧版本docker

sudo apt-get remove docker docker-engine docker.io containerd runc

安装docker

# 更新软件索引
sudo apt-get update

# 安装必备软件
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

# 安装 apt-key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# 添加 repository
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

# 更新软件索引
sudo apt-get update

# 安装docker
sudo apt-get install docker-ce docker-ce-cli containerd.io

# 检验docker是否安装成功
sudo docker run hello-world

配置docker

使用 root 权限创建 ‘/etc/docker/daemon.json’ 文件,并填写以下内容:

{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"]
}

重启docker

sudo systemctl daemon-reload
sudo systemctl restart docker

当前用户加入docker用户组

# 建立docker组
sudo groupadd docker
# 将当前用户加入docker组
sudo usermod -aG docker $USER

安装 Kubernetes

添加 apt-key.gpg 步骤可能需要梯子,可以通过手动下载 apt-key.gpg,再用这个命令 cat /mnt/c/Users/huang/Downloads/apt-key.gpg | sudo apt-key add -/mnt/c/ 表示挂载 C盘,后面加上 apt-key.gpg 所在目录;

如果不能科学上网的话,我们可以使用阿里云的源进行安装:

sudo apt-get update && sudo apt-get install -y apt-transport-https curl
# 添加apt-key.gpg 使用阿里源
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo 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
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

:::warning kubeadm 初始化报错:

  • kubelet 默认 cgroupdriver 是 cgroupfs,但是 k8s 竟然推荐用 systemd
  • 分别修改 docker 与控制平台的 kubelet 为 systemd 【官方推荐】
    • 重置未初始化成功的 kubeadm 配置: sudo kubeadm reset
    • 修改 docker,只需在 /etc/docker/daemon.json 中,添加 "exec-opts": ["native.cgroupdriver=systemd"] 即可
    • 修改 kubelet
    • 重启 docker 与 kubelet ```bash

      修改 kubelet

      cat > /var/lib/kubelet/config.yaml <<EOF apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd EOF

重启 docker 与 kubelet

systemctl daemon-reload systemctl restart docker systemctl restart kubelet

:::


<a name="pK3Gu"></a>
## 启动 k8s 集群
执行 `kubeadm init` 命令之前,先下载必要的镜像,运行以下命令:
```bash
 kubeadm config images list --kubernetes-version=v1.18.8

得到以下结果:(冒号后面是镜像的版本,会根据kubeadm版本而变化)

k8s.gcr.io/kube-apiserver:v1.18.6
k8s.gcr.io/kube-controller-manager:v1.18.6
k8s.gcr.io/kube-scheduler:v1.18.6
k8s.gcr.io/kube-proxy:v1.18.6
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.7

k8s.gcr.io 镜像在国内多半是拉取失败的,所以要把 k8s.gcr.io 前缀换成 gotok8s ,再加上 ‘docker pull’:

docker pull gotok8s/kube-apiserver:v1.18.6
docker pull gotok8s/kube-controller-manager:v1.18.6
docker pull gotok8s/kube-scheduler:v1.18.6
docker pull gotok8s/kube-proxy:v1.18.6
docker pull gotok8s/pause:3.2
docker pull gotok8s/etcd:3.4.3-0
docker pull gotok8s/coredns:1.6.7

逐行执行以上命令,待全部完成后,再通过 docker tag 命令,把镜像标签改成 k8s.gcr.io

docker tag gotok8s/kube-apiserver:v1.18.6 k8s.gcr.io/kube-apiserver:v1.18.6
docker tag gotok8s/kube-controller-manager:v1.18.6 k8s.gcr.io/kube-controller-manager:v1.18.6
docker tag gotok8s/kube-scheduler:v1.18.6 k8s.gcr.io/kube-scheduler:v1.18.6
docker tag gotok8s/kube-proxy:v1.18.6 k8s.gcr.io/kube-proxy:v1.18.6
docker tag gotok8s/pause:3.2 k8s.gcr.io/pause:3.2
docker tag gotok8s/etcd:3.4.3-0 k8s.gcr.io/etcd:3.4.3-0
docker tag gotok8s/coredns:1.6.7 k8s.gcr.io/coredns:1.6.7

再执行以下命令,等待数分钟后,即可搭建一个标准版 k8s 集群

sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --kubernetes-version=v1.18.8

出现以下命令时,说明创建 k8s 集群成功,再按照提示执行以下命令:(如果创建集群失败,通过运行 sudo kubeadm reset,然后输入 Y 即可清除 kubeadm init 命令的操作)

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

最后一步,通过 kubectl apply 命令,安装 CNI 插件,这里以 flannel 为例:

$ wget https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml
# 因为有节点是多网卡,所以需要在资源清单文件中指定内网网卡
# 搜索到名为 kube-flannel-ds-amd64 的 DaemonSet,在kube-flannel容器下面
$ vi kube-flannel.yml
......
containers:
- name: kube-flannel
  image: quay.io/coreos/flannel:v0.11.0-amd64
  command:
  - /opt/bin/flanneld
  args:
  - --ip-masq
  - --kube-subnet-mgr
  - --iface=eth0  # 如果是多网卡的话,指定内网网卡的名称
......
$ kubectl apply -f kube-flannel.yml  # 安装 flannel 网络插件

如果安装 Calico 的话:

kubectl apply -f https://docs.projectcalico.org/v3.14/manifests/calico.yaml

通过 kubectl get node 命令获取 node 节点的状态是否 ready

NAME              STATUS   ROLES    AGE   VERSION
k8s-master   Ready    master   11m   v1.18.6

为了使用更便捷,启用 kubectl 命令的自动补全功能。

echo "source <(kubectl completion bash)" >> ~/.bashrc

安装 Dashboard

v1.18 版本的集群需要安装最新的 2.0+ 版本的 Dashboard:

# 推荐使用下面这种方式
$ wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta5/aio/deploy/recommended.yaml
$ vi recommended.yaml
# 修改Service为NodePort类型
......
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard
  type: NodePort  # 加上type=NodePort变成NodePort类型的服务
......

监控组件
在 YAML 文件中可以看到新版本 Dashboard 集成了一个 metrics-scraper 的组件,可以通过 Kubernetes 的 Metrics API 收集一些基础资源的监控信息,并在 web 页面上展示,所以要想在页面上展示监控信息就需要提供 Metrics API,比如安装 Metrics Server。

直接创建:

$ kubectl apply -f recommended.yaml

新版本的 Dashboard 会被默认安装在 kubernetes-dashboard 这个命名空间下面:

$ kubectl get pods -n kubernetes-dashboard -l k8s-app=kubernetes-dashboard
NAME                                  READY   STATUS    RESTARTS   AGE
kubernetes-dashboard-fcfb4cbc-t462n   1/1     Running   0          50m
$ kubectl get svc -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
dashboard-metrics-scraper   ClusterIP   10.102.124.146   <none>        8000/TCP       21s
kubernetes-dashboard        NodePort    10.106.254.187   <none>        443:30750/TCP   22s

然后可以通过上面的 30750 端口去访问 Dashboard,要记住使用 https,Chrome 不生效可以使用Firefox 测试,如果没有 Firefox 下面打不开页面,可以点击下页面中的信任证书即可:

在 WSL2 上部署标准 k8s 单主节点 - 图1
信任后就可以访问到 Dashboard 的登录页面了:

在 WSL2 上部署标准 k8s 单主节点 - 图2

然后创建一个具有全局所有权限的用户来登录Dashboard:(admin.yaml)

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: admin
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: admin
  namespace: kubernetes-dashboard

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin
  namespace: kubernetes-dashboard

直接创建:

$ kubectl apply -f admin.yaml
$ kubectl get secret -n kubernetes-dashboard|grep admin-token
admin-token-lwmmx                  kubernetes.io/service-account-token   3         1d
$ kubectl get secret admin-token-lwmmx -o jsonpath={.data.token} -n kubernetes-dashboard |base64 -d# 会生成一串很长的base64后的字符串

然后用上面的 base64 解码后的字符串作为 token 登录 Dashboard 即可,新版本还新增了一个暗黑模式:

在 WSL2 上部署标准 k8s 单主节点 - 图3

Pod 调度到 Master 节点

出于安全考虑,默认配置下 Kubernetes 不会将 Pod 调度到 Master 节点。查看 Taints 字段默认配置:

$ kubectl describe node k8s-master 
......
Taints:             node-role.kubernetes.io/master:NoSchedule

如果希望将 k8s-master 也当作 Node 节点使用,可以执行如下命令,其中 k8s-master 是主机节点hostname:

kubectl taint node k8s-master node-role.kubernetes.io/master-

修改后Taints字段状态:

$ kubectl describe node k8s-master                             
......
Taints:             <none>

如果要恢复Master Only状态,执行如下命令:

$ kubectl taint node k8s-master node-role.kubernetes.io/master=""