# 详细记录用kubeadm在Ubuntu上安装Kubernetes集群

# 1 前言

之前写了篇文章《Mac上使用Docker Desktop启动Kubernetes,踩坑后终于搞掂 (opens new window)》介绍了如何搭建一个Kubernetes玩玩,但毕竟是单机版,今天我们来学习一下如何搭建Kubernetes集群,更贴近生产,但还不能用于生产。

# 2 基本概念

首先贴一张来自官网的图:

通过这张图,我们就能大概知道我们需要安装什么,如何安装,而不是瞎操作。

# 2.1 控制面-master节点

左边是控制面,也就是master节点,需要有:

etcd作为存储集群信息的键值对数据库;

kube-api-server对外公开K8s API,是控制面的前端;

kube-scheduler监视那些新创建的未指定运行节点的Pod,并选择节点让Pod在上面运行;

kube-controller-manager控制器组件,如节点控制器、副本控制器、端点控制器等。

# 2.2 Node节点

右边是Node节点,即计算和工作节点:

kubelet在每个节点运行的代理,它保证容器运行在Pod中;

kube-proxy是节点的网络代理。

# 2.3 版本信息

本次操作的版本信息如下:

组件 版本号 说明
操作系统 Ubuntu 18.04 阿里云机器,2Cpu 4Gb内存
Docker 19.3.13 apt安装
Kubernetes v1.19.0 apt安装和容器化安装

# 3 机器准备

登陆阿里云 (opens new window),没有账号可以用支付宝登陆创建,购买机器时需要保证账号有100元,是因为很多服务是先使用、后付费的模式。登陆后进入控制台,点击左侧的云服务器ECS,然后点击创建实例

# 3.1 机型选择

我之前已经有3台广州地区的机器了,这次例子我买华北地区的吧:

注意要选抢占式实例,比较便宜;

地区就近原则就行,离你越近,网络连接应该越好,后面可用区要选一个,不要随机分配

性能方面就选2Cpu 4Gb

买3台,一台master,两台node

系统镜像选Ubuntu 18.04 64位

它会根据你的选择把价格实时计算出来,可以选一个最便宜的。

其它默认,按下一步。

# 3.2 网络设置

网络设置如下:

注意要分配公网IP,不然无法连接;

选择按流量计费,因为按带宽计费很贵,然后把带宽峰值调到最大,加快后面下载软件和镜像;

安全组把端口都打开吧。

# 3.3 设置密码

设置root的登陆密码:

可能通过密钥或密码登陆,这里直接用密码的方式。

接着后面正常选就行了。

# 3.4 ssh连接测试

创建成功后,查看一下:

如果查看不到,就刷新一下,并选择对应的地区。可以看到上面三台机器的内网IP在都一个段上,完美!

通过ssh软件和命令连接,测试是否正常,注意是要用公网的IP,如:

ssh root@39.104.25.81

# 4 搭建过程

# 4.1 系统基本设置

分别去对应的机器下配置一下hostname,注意一台机器只执行其中一条命令:

hostnamectl set-hostname master01 --static
hostnamectl set-hostname node01 --static
hostnamectl set-hostname node02 --static

修改完后执行su,就能看到变化了。

修改/etc/hosts文件,注意下面是内网IP(三台机器都执行):

# pkslow-cluster
172.21.243.113    master01
172.21.243.114    node01
172.21.243.115    node02

关闭防火墙(三台机器都执行):

ufw disable

# 4.2 安装Docker(三台机器都执行)

# 4.2.1 必要的软件及密钥准备

更新源:

apt-get update

安装软件包以允许apt通过HTTPS使用存储库:

apt-get -y install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

添加Docker的官方GPG密钥:

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

添加稳定的存储库:

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

更新apt源:

apt-get update

# 4.2.2 安装docker

安装docker-ce最新版本:

apt-get -y install docker-ce docker-ce-cli containerd.io

这里装的东西比较大,可能需要等一段时间。

查看安装情况:

docker info

可能会出现警告:WARNING: No swap limit support,这会影响后续对Docker进行资源限制。

解决方案:修改/etc/default/grub文件的如下配置为:

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1 vga=792 console=tty0 console=ttyS0,115200n8 net.ifnames=0 noibrs"

更新后重启让它生效:

update-grub && reboot

将系统iptables 中 FORWARD 链的默认策略设置为ACCEPT

echo "iptables -P FORWARD ACCEPT" >> ~/.bashrc
source ~/.bashrc

# 4.2.3 阿里云镜像加速

设置阿里云镜像加速:

cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": ["https://v00rv7a3.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

重启Docker

systemctl daemon-reload && systemctl restart docker.service

# 4.3 安装Kubernetes

# 4.3.1 安装必备软件包

安装软件kubeletkubeadmkubectl(三台机器都执行):

# 配置apt
apt-get update && apt-get install -y apt-transport-https
# 配置key
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - 
# 添加阿里云镜像
cat <<EOF >/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

开启这些设置使通过网桥的数据包由主机系统上的iptables规则处理,默认关闭,设置为1则开启:

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

sudo sysctl --system

# 4.3.2 控制面创建(只在master主机)

生成配置文件:

kubeadm config print init-defaults >  init-defaults.yaml

修改配置文件init-defaults.yaml的如下信息:

clusterName: pkslow-cluster
advertiseAddress: 172.21.243.113
imageRepository: registry.aliyuncs.com/google_containers

初始化master

kubeadm init --config init-defaults.yaml

成功后会有如下信息,并给出了node节点如何加入集群的命令,把下面标红的命令复制下来:

# 4.3.3 节点加入集群

在两个节点(node01和node02)执行:

kubeadm join 172.21.243.113:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:2b425f0cb1f2609992ed8e3e3da2fd1c9db1f02381a7d8dcc9bfa4b5e607de97

# 4.3.4 检测集群情况(只在master)

kubectl指定配置文件:

echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /root/.bashrc
source /root/.bashrc

查看所有节点的状态:

 kubectl get nodes
NAME       STATUS     ROLES    AGE     VERSION
master01   NotReady   master   3m21s   v1.19.3
node01     NotReady   <none>   71s     v1.19.3
node02     NotReady   <none>   56s     v1.19.3

发现STATUSNotReady,是因为我们还没有安装网络组件。

安装网络:

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

再次检测,已经Ready了:

 kubectl get nodes
NAME       STATUS   ROLES    AGE     VERSION
master01   Ready    master   4m32s   v1.19.3
node01     Ready    <none>   2m22s   v1.19.3
node02     Ready    <none>   2m7s    v1.19.3

# 5 验证

# 5.1 集群验证

查看集群信息:

# kubectl cluster-info
Kubernetes master is running at https://172.21.243.113:6443
KubeDNS is running at https://172.21.243.113:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

查看关键组件有没有正常运行:

# kubectl get pods -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-6dfcd885bf-9x7dp   1/1     Running   0          8h
calico-node-5fvm6                          1/1     Running   0          8h
calico-node-ftkmk                          1/1     Running   0          8h
calico-node-ql8jd                          1/1     Running   0          8h
coredns-6d56c8448f-49ld7                   1/1     Running   0          8h
coredns-6d56c8448f-hf9qv                   1/1     Running   0          8h
etcd-master01                              1/1     Running   0          8h
kube-apiserver-master01                    1/1     Running   0          8h
kube-controller-manager-master01           1/1     Running   0          8h
kube-proxy-49r5z                           1/1     Running   0          8h
kube-proxy-65pgs                           1/1     Running   0          8h
kube-proxy-9w5h2                           1/1     Running   0          8h
kube-scheduler-master01                    1/1     Running   0          8h

# 5.2 运行一个应用验证

启动一个nginx试试:

kubectl run nginx --image=nginx:1.19.0

查看发现已经正常运行:

kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP                NODE     NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          7h59m   192.168.196.130   node01   <none>           <none>

发送GET请求,查看nginx的首页:

curl http://192.168.196.130

# 6 其它补充

该部分与之前使用的机器不同,IP已经变化。

# 6.1 给node添加label

安装完成后,节点显示的角色为空,需要添加标签:

kubectl label nodes node01 node-role.kubernetes.io/worker=
kubectl label nodes node02 node-role.kubernetes.io/worker=

这样就会正常显示角色:

$ kubectl get node
NAME       STATUS   ROLES    AGE     VERSION
master01   Ready    master   7h34m   v1.19.4
node01     Ready    worker   7h32m   v1.19.4
node02     Ready    worker   7h31m   v1.19.4

# 6.2 安装Ingress Controller

使用Github上的一个yaml文件直接apply:https://github.com/kubernetes/ingress-nginx/blob/ingress-nginx-3.10.1/deploy/static/provider/baremetal/deploy.yaml

但需要多添加一行代码,即在Deployment上添加hostNetwork: true,这样这些Pod就会使用宿主的网络。添加如下:

spec:
	hostNetwork: true
  dnsPolicy: ClusterFirst
  containers:
  - name: controller

位置大概如图所示:

找到所在的node,为node01

$ kubectl get pod -A -o wide | grep ingress
ingress-nginx   ingress-nginx-admission-create-j82j4       0/1     Completed   0          26m     192.168.140.69    node02     <none>           <none>
ingress-nginx   ingress-nginx-admission-patch-lpw7t        0/1     Completed   0          26m     192.168.196.137   node01     <none>           <none>
ingress-nginx   ingress-nginx-controller-89bd8fb7c-zsnnx   1/1     Running     0          14m     172.17.144.117    node01     <none>           <none>

则使用了Ingress后,要按下面访问:

curl 172.17.144.117/nginx

# 6.3 安装Storage Class

需要安装一个StorageClass,以便做其它实验。

# 6.3.1 安装NFS服务器

使用主节点做NFS服务器,在master节点安装如下:

apt-get -y install nfs-kernel-server

创建目录并赋权:

mkdir /storage && echo "/storage *(rw,sync,no_root_squash)" >> /etc/exports
# 重启
systemctl restart nfs-kernel-server

# 6.3.2 node节点安装客户端

我们只在node节点作为客户端,则只在node节点安装:

apt-get -y install nfs-common

# 6.3.3 部署NFS Client插件

Github (opens new window)下载class.yamlrbac.yamldeployment.yaml文件,修改deployment.yaml文件的服务器IP和目录:

          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 172.17.144.116
            - name: NFS_PATH
              value: /storage
      volumes:
        - name: nfs-client-root
          nfs:
            server: 172.17.144.116
            path: /storage

全部apply

# 6.3.4 测试

创建一个StatefulSet来测试:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx 
  serviceName: "nginx"
  replicas: 3 
  template:
    metadata:
      labels:
        app: nginx 
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteMany" ]
      storageClassName: "managed-nfs-storage"
      resources:
        requests:
          storage: 10Mi

检查:

$ kubectl get statefulsets.apps 
NAME   READY   AGE
web    3/3     7m43s
$ ls /storage/
default-www-web-0-pvc-5379c52c-d052-4877-a0c2-8a04807a932c  default-www-web-1-pvc-178bb758-d65d-44e8-86bc-137b727e996d  default-www-web-2-pvc-21cddeb8-8612-4413-9ab9-7be8fbcb3a96

StatefulSet正常启动,在/storage目录成功创建了目录。

# 6.4 安装Metrics Server

安装前,无法获取:

kubectl top node
error: Metrics API not available

下载安装脚本:

wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.7/components.yaml

修改components.yaml文件,在deploymentargs增加参数如下:

args:
	- --kubelet-insecure-tls
  - --kubelet-preferred-address-types=InternalIP

apply后,等一段时间,执行即可:

$ kubectl top node
NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
master01   172m         8%     2039Mi          53%       
node01     124m         6%     1612Mi          41%       
node02     136m         6%     1433Mi          37%

# 7 重置集群

在三台机执行:

kubeadm reset
rm -rf /etc/kubernetes

对于master节点,还要执行:

rm -rf /var/lib/calico

然后重新执行:

kubeadm init --config init-defaults.yaml 
kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml

node节点重新join就行了。当然,Ingress Controller等也要重新安装了。

# 8 总结

这是用于实验的搭建,实际生产环境会更复杂,起码master不能是单节点,要高可用。但对于学习Kubernetes而言,可以满足了。

上次更新: 2023/8/18 23:39:36