节点说明

系统类型 IP地址 节点角色 Hostname
centos-7.4 192.168.43.111 master vmware-111
centos-7.4 192.168.43.112 worker vmware-112
centos-7.4 192.168.43.113 master vmware-113
  • 因为服务器有限,所以这里设置master也承担工作负载

环境准备

系统设置

主机名配置

  • 主机名必须每个节点都不一样,并且保证所有点之间可以通过hostname互相访问

    1
    2
    3
    4
    5
    6
    7
    # 查看主机名
    $ hostname
    # 修改主机名
    $ hostnamectl set-hostname <your_hostname>
    # 配置host,使所有节点之间可以通过hostname互相访问
    $ vi /etc/hosts
    # <node-ip> <node-hostname>
    1. 配置hosts文件(全部主机)

      1
      2
      3
      4
      $ vi /etc/hosts
      192.168.43.111 vmware-111
      192.168.43.112 vmware-112
      192.168.43.113 vmware-113
    2. 配置各个主机的hostname(全部主机)

      1
      2
      3
      4
      5
      6
      7
      8
      # 192.168.43.111
      $ hostnamectl set-hostname vmware-111

      # 192.168.43.112
      $ hostnamectl set-hostname vmware-112

      # 192.168.43.113
      $ hostnamectl set-hostname vmware-113

安装依赖包(全部节点)

1
2
3
4
# 更新yum
$ yum update -y
# 安装依赖包
$ yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp

功能设置(全部节点)

1
2
3
4
5
6
7
8
9
# 关闭防火墙,如果不想关闭防火墙可以看下方的集群所需端口列表
$ systemctl stop firewalld && systemctl disable firewalld
# 关闭swap
$ swapoff -a
$ sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab
# 关闭selinux
$ setenforce 0
# 关闭dnsmasq(否则可能导致docker容器无法解析域名)
$ service dnsmasq stop && systemctl disable dnsmasq

系统参数设置(全部节点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 制作配置文件
$ cat > /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
EOF
# 生效文件
$ sysctl -p /etc/sysctl.d/kubernetes.conf

# 如果net.bridge.bridge-nf-call-iptables报错,加载br_netfilter模块
$ modprobe br_netfilter
$ sysctl -p /etc/sysctl.d/kubernetes.conf

安装docker(全部节点)

  • 自行找教程

  • docker配置

    1
    2
    3
    4
    # 在/etc/docker/daemon.json加入
    "exec-opts": ["native.cgroupdriver=systemd"]
    # 启动docker服务
    service docker restart

创建目录(全部节点)

1
2
3
mkdir -p /opt/keepalived
mkdir -p /opt/kubernetes
mkdir -p /etc/kubernetes

安装必要工具(全部节点)

工具说明

  • kubeadm: 部署集群用的命令
  • kubelet: 在集群中每台机器上都要运行的组件,负责管理pod、容器的生命周期
  • kubectl: 集群管理工具(可选,只要在控制集群的节点上安装即可)

安装方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 配置yum源
$ cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# 安装工具
# 找到要安装的版本号
$ yum list kubeadm --showduplicates | sort -r

# 安装指定版本(这里用的是1.15.1)
$ yum install -y kubeadm-1.15.1-0 kubelet-1.15.1-0 kubectl-1.15.1-0 --disableexcludes=kubernetes

$ systemctl daemon-reload

# 启动kubelet
$ systemctl enable kubelet && systemctl start kubelet

准备配置文件(任意选一个节点:192.168.43.111)

1
2
3
4
5
6
7
8
$ cd /opt/kubernetes && git clone https://github.com/chcGolang/k8s-kubeadm
# 看看git内容
$ ls -l k8s-kubeadm
addons/
configs/
scripts/
init.sh
global-configs.properties

文件说明

  • addons

kubernetes的插件,比如calico和dashboard。

  • configs

包含了部署集群过程中用到的各种配置文件。

  • scripts

包含部署集群过程中用到的脚本,如keepalive检查脚本。

  • global-configs.properties

全局配置,包含各种易变的配置内容。

  • init.sh

初始化脚本,配置好global-config之后,会自动生成所有配置文件。

生成配置

1
2
3
4
5
6
7
8
9
10
11
# cd到之前下载的git代码目录
$ cd k8s-kubeadm

# 编辑属性配置(根据文件注释中的说明填写好每个key-value)
$ vi global-config.properties

# 生成配置文件,确保执行过程没有异常信息
$ ./init.sh

# 查看生成的配置文件,确保脚本执行成功
$ find target/ -type f

执行init.sh常见问题:

  1. Syntax error: “(“ unexpected
  • bash版本过低,运行:bash -version查看版本,如果小于4需要升级
  • 不要使用 sh init.sh的方式运行(sh和bash可能不一样哦)
  1. global-config.properties文件填写错误,需要重新生成
    再执行一次./init.sh即可,不需要手动删除target

集群安装

安装keepalived(选择两个以上的Master节点)

  1. 创建配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    #  192.168.43.113(主)
    cat>/opt/keepalived/keepalived.conf<<EOF

    vrrp_instance VI_1 {
    state BACKUP ## 主节点为MASTER,备份节点为BACKUP
    interface ens33 ## 绑定虚拟IP的网络接口(网卡),与本机IP地址所在的网络接口相同(服务器主机网卡)
    virtual_router_id 111 ## 虚拟路由ID号(主备节点一定要相同)
    mcast_src_ip 192.168.43.113 ## 本机ip地址
    priority 100 ##优先级配置(0-254的值)
    nopreempt
    advert_int 1 ## 组播信息发送间隔,俩个节点必须配置一致,默认1s
    authentication { ## 认证匹配
    auth_type PASS
    auth_pass rabbitmq
    }
    virtual_ipaddress {
    192.168.43.101 ## 虚拟ip,可以指定多个
    }
    }

    EOF


    # 192.168.43.111(备)
    cat>/opt/keepalived/keepalived.conf<<EOF

    vrrp_instance VI_1 {
    state BACKUP ## 主节点为MASTER,备份节点为BACKUP
    interface ens33 ## 绑定虚拟IP的网络接口(网卡),与本机IP地址所在的网络接口相同(服务器主机网卡)
    virtual_router_id 111 ## 虚拟路由ID号(主备节点一定要相同)
    mcast_src_ip 192.168.43.111 ## 本机ip地址
    priority 98 ##优先级配置(0-254的值)
    nopreempt
    advert_int 1 ## 组播信息发送间隔,俩个节点必须配置一致,默认1s
    authentication { ## 认证匹配
    auth_type PASS
    auth_pass rabbitmq
    }
    virtual_ipaddress {
    192.168.43.101 ## 虚拟ip,可以指定多个
    }
    }

    EOF
  2. 启动keepalived

    1
    2
    3
    4
    5
    6
    docker run -d --net=host \
    --privileged \
    --name keepalived \
    --restart=unless-stopped \
    -v /opt/keepalived/keepalived.conf:/container/service/keepalived/assets/keepalived.conf \
    osixia/keepalived --copy-service
  3. 查看ip

    1
    ip addr

部署第一Master节点(192.168.43.113)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 准备配置文件
# 在192.168.43.111拷贝配置文件到192.168.43.113
$ scp target/configs/kubeadm-config.yaml root@192.168.43.113:/opt/kubernetes/
# ssh到192.168.43.113,执行kubeadm初始化系统(注意保存最后打印的加入集群的命令)
$ kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs

# 如果出现:Error writing Crisocket information for the control-plane node: timed out waiting for the condition
# 重启kubeadm
kubeadm reset
# 在执行init命令

# copy kubectl配置(上一步会有提示)
$ mkdir -p ~/.kube
$ cp -i /etc/kubernetes/admin.conf ~/.kube/config

# 测试一下kubectl
$ kubectl get pods --all-namespaces

# 查看10-kubeadm.conf配置文件的位置
$ systemctl status kubelet
# 设置kubelet的cgroupdriver为systemd第一Master节点(192.168.43.113)的,其他不用
$ vi /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
# 加入--cgroup-driver=systemd
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml --cgroup-driver=systemd"
#或者修改/kubelet/config.yaml配置文件第
$ vi /var/lib/kubelet/config.yaml
cgroupDriver: cgroupfs 改成 cgroupDriver: systemd
$ systemctl restart kubelet

# **备份init打印的join命令**
You can now join any number of the control-plane node running the following command on each as root:
# master节点用以下命令加入集群:
kubeadm join 192.168.43.101:6443 --token jlk7g0.kh4d6pxo261li90n \
--discovery-token-ca-cert-hash sha256:0ca7858e22de721bbdf385ffeba34868b7328545de1ef221a05b5b3c029d647e \
--control-plane --certificate-key b29d615dcc4ddc0606067d06bf5bfba5681c80616373465fa0c362594c29927b

Then you can join any number of worker nodes by running the following on each as root:
# 工作节点用以下命令加入集群:
kubeadm join 192.168.43.101:6443 --token jlk7g0.kh4d6pxo261li90n \
--discovery-token-ca-cert-hash sha256:0ca7858e22de721bbdf385ffeba34868b7328545de1ef221a05b5b3c029d647e

部署网络插件 - calico (192.168.43.113)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建目录(192.168.43.113)
$ mkdir -p /etc/kubernetes/addons

# 上传calico配置到配置好kubectl的节点(192.168.43.111)
$ scp target/addons/calico* root@192.168.43.113:/etc/kubernetes/addons/

# 查看需要的image
$ cat /etc/kubernetes/addons/calico.yaml |grep image
# 然后使用docker pull命令下载下来
$ docker pull ...

# 部署calico (192.168.43.113)
$ kubectl apply -f /etc/kubernetes/addons/calico-rbac-kdd.yaml
$ kubectl apply -f /etc/kubernetes/addons/calico.yaml

# 查看状态 (192.168.43.113)
$ kubectl get pods -n kube-system

加入其它master节点

1
2
3
4
5
6
7
8
9
10
11
12
# 使用之前保存的join命令加入集群(192.168.43.112)
kubeadm join 192.168.43.101:6443 --token jlk7g0.kh4d6pxo261li90n \
--discovery-token-ca-cert-hash sha256:0ca7858e22de721bbdf385ffeba34868b7328545de1ef221a05b5b3c029d647e \
--control-plane --certificate-key b29d615dcc4ddc0606067d06bf5bfba5681c80616373465fa0c362594c29927b

# 耐心等待一会,并观察日志
$ journalctl -f
# 查看集群状态
# 1.查看节点
$ kubectl get nodes
# 2.查看pods
$ kubectl get pods --all-namespaces

加入worker节点

1
2
3
4
5
6
7
8
# 使用之前保存的join命令加入集群
$ kubeadm join ...

# 耐心等待一会,并观察日志
$ journalctl -f

# 查看节点
$ kubectl get nodes

其他命令

  • 让master节点也承载工作负荷(生产环境不推荐使用)

    1
    2
    3
    kubectl taint nodes --all node-role.kubernetes.io/master-
    # 这个错误可以忽略
    error: taint “node-role.kubernetes.io/master:” not found
  • 禁止master部署pod

    1
    kubectl taint nodes k8s node-role.kubernetes.io/master=true:NoSchedule

问题解决

  • 查看问题方法

    1
    2
    systemctl status kubelet
    journalctl -f
  • skipping: failed to "StartContainer" for "coredns" with CrashLoopBackOff: "B

    1
    2
    3
    4
    # 执行命令
    kubectl -n kube-system get deployment coredns -o yaml | \
    sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
    kubectl apply -f -

集群可用性测试

1. 创建nginx ds

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 # 写入配置
$ cat > nginx-ds.yml <<EOF
apiVersion: v1
kind: Service
metadata:
name: nginx-ds
labels:
app: nginx-ds
spec:
type: NodePort
selector:
app: nginx-ds
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: nginx-ds
labels:
addonmanager.kubernetes.io/mode: Reconcile
spec:
template:
metadata:
labels:
app: nginx-ds
spec:
containers:
- name: my-nginx
image: nginx:1.7.9
ports:
- containerPort: 80
EOF

# 创建ds
$ kubectl create -f nginx-ds.yml


2. 检查各种ip连通性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 检查各 Node 上的 Pod IP 连通性
$ kubectl get pods -o wide

# 在每个节点上ping pod ip
$ ping <pod-ip>

# 检查service可达性
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h5m
nginx-ds NodePort 10.101.25.8 <none> 80:32146/TCP 8m30s

# 在每个节点上访问服务
$ curl <service-ip>:<port>
# curl 10.101.25.8:80

# 在每个节点检查node-port可用性
$ curl <node-ip>:<port>
# curl 192.168.43.111:32146



3. 检查dns可用性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 创建一个nginx pod
$ cat > pod-nginx.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
EOF

# 创建pod
$ kubectl create -f pod-nginx.yaml

# 进入pod,查看dns
$ kubectl exec nginx -i -t -- /bin/bash

# 查看dns配置
root@nginx:/# cat /etc/resolv.conf

# 查看名字是否可以正确解析
root@nginx:/# ping nginx-ds