0%

从零开始搭建k8s集群环境(番外)——纯手动部署全套

从零开始搭建 k8s 集群环境系列笔记:

今天周末,沉浸在 k8s 集群部署完成带来的极大满足中开始回顾之前看过的关于 k8s 的各种博客。。。然后,我觉得很有必要补一篇纯手动部署的文章。。。

环境说明:

  • Master:VBox虚拟机/Centos_7.5-1804/192.168.56.100
  • Images:VBox虚拟机/Centos_7.5-1804/192.168.56.101
  • Node01:VBox虚拟机/Centos_7.5-1804/192.168.56.102

软件环境说明:

  • docker-ce-18.03.1
  • kubernetes-v1.10.4
  • etcd-v3.3.7
  • flannel-v0.10.0

为什么补一篇

之所以还要补一篇,是因为之前七篇博客说得部署 k8s,都是用的 k8s 自带的 kubeadm 这个程序在部署,比如 kubeadm initkubeadm join 什么的,这也是高版本 k8s 中官方推荐的部署方式。

然后,我们回过头来看之前的整个部署过程:

  1. 安装 DockerKubeletKubectlKubeadmcni
  2. 执行 kubeadm init 初始化 Masterkubeadm 写入初始化信息,kubelet 服务开始退出循环等待开始正常工作。
  3. kubelet 服务初始化加载 pause-amd64etcd-amd64kube-apiserver-amd64kube-scheduler-amd64kube-controller-manager-amd64 核心 Pod。
  4. 然后安装 Pod 网络,kubelet 又开始加载 flannelk8s-dns-sidecar-amd64k8s-dns-kube-dns-amd64k8s-dns-dnsmasq-nanny-amd64 等网络相关 Pod。
  5. 经过以上步骤,我们的集群实际上已经开始工作。我们再接着就是部署一些附加服务。

不知道大家在部署过程中有没有注意到:当我们执行 kubeadm init 的时候,从控制台输出我们可以看到 kubeadm 先是启动 kubelet 服务,然后是自检,再然后写入配置、生成证书和预部署服务(/etc/kubernetes/manifests/)。我们基本可以确认:
kubeadm 这个程序实际上是一个 k8s 的引导程序(额、好像说的是废话。。。),由它启动 kubelet 并运行需要的 Pod,每个 Pod 提供不同的服务,组成 k8s 集群基本系统。

而网络上流传的版本,大多都是手动安装 k8s 的各个组件,比如 etcdflannel等,这种做法虽然目前不是 k8s 官方推荐的,但考虑到如果 k8s 是部署到机型各不相同的物理环境,也不失是一个自定义 Node 的办法。

所以,为了更全面覆盖 k8s 集群部署内容,就补这么一篇不使用 kubeadm 的手动部署的过程记录。

环境准备

在操作之前,我们先处理所有节点都要做的事情:

禁用交换分区

# 关闭
swapoff -a

# 禁用
sed -i "s/\/dev\/mapper\/centos-swap/# \/dev\/mapper\/centos-swap/g" /etc/fstab

关闭防火墙

# 关闭并禁用
systemctl stop firewalld && systemctl disable firewalld

禁用SELinux

# 关闭
setenforce 0

# 禁用
sed -i "s/SELINUX=enforcing/SELINUX=disable/g" /etc/selinux/config

设置IPV4转发内核参数

cat>/etc/sysctl.d/kubernetes.conf<<'EOF'
net.ipv4.ip_forward=1
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
EOF

modprobe br_netfilter
sysctl -p /etc/sysctl.d/kubernetes.conf

签发证书

kubernetes 系统各组件需要使用 TLS 证书对通信进行加密,本文档使用 CloudFlarePKI 工具集 cfssl 来生成 Certificate Authority (CA) 证书和秘钥文件,CA 是自签名的证书,用来签名后续创建的其它 TLS 证书。

由于无证书版各种配置没有文档,部署之后 DNS 不能正常工作,楼主实验 N^n 次之后实在是无解,所以最后还是加了证书。

准备

下载 cfssl 工具

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64
chmod +x cfssljson_linux-amd64
chmod +x cfssl-certinfo_linux-amd64
mv -f cfssl_linux-amd64 /usr/bin/cfssl
mv -f cfssljson_linux-amd64 /usr/bin/cfssljson
mv -f cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo

写入证书配置文件

cat >config.json<<EOF
{
  "signing": {
    "default": {
      "expiry": "8760h"
    },
    "profiles": {
      "profile": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "8760h"
      }
    }
  }
}
EOF

生成 CA 证书

# 创建文件夹
mkdir ca
# 写入证书请求文件
cat >ca/ca-csr.json<<EOF
{
  "CN": "Kubernetes CA",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 4096
  },
  "names": [
    {
      "C": "CN",
      "ST": "ChengDu",
      "L": "ChengDu",
      "O": "Kubernetes",
      "OU": "System"
    }
  ]
}
EOF

# 生成证书
cd ca && cfssl gencert -initca ca-csr.json | cfssljson -bare ca && cd ..

生成 Etcd 证书

# 创建文件夹
mkdir etcd
# 写入证书请求文件
cat >etcd/etcd-csr.json<<EOF
{
    "CN": "etcd",
    "hosts": [
      "127.0.0.1",
      "10.1.0.1",
      "10.2.0.1",
      "192.168.56.100",
      "192.168.56.101",
      "192.168.56.102",
      "192.168.56.103",
      "192.168.56.104",
      "192.168.56.105",
      "192.168.56.106",
      "192.168.56.107",
      "192.168.56.108",
      "192.168.56.109",
      "192.168.56.110",
      "kubernetes",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 4096
    },
    "names": [
        {
            "C": "CN",
            "ST": "ChengDu",
            "L": "ChengDu",
            "O": "Kubernetes",
            "OU": "System"
        }
    ]
}
EOF

# 生成证书
cd etcd && cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../config.json -profile=profile etcd-csr.json | cfssljson -bare etcd && cd ..

生成 Master 证书

# 创建文件夹
mkdir master
# 写入证书请求文件
cat >master/master-csr.json<<EOF
{
    "CN": "master",
    "hosts": [
      "127.0.0.1",
      "10.1.0.1",
      "10.2.0.1",
      "192.168.56.100",
      "192.168.56.101",
      "192.168.56.102",
      "192.168.56.103",
      "192.168.56.104",
      "192.168.56.105",
      "192.168.56.106",
      "192.168.56.107",
      "192.168.56.108",
      "192.168.56.109",
      "192.168.56.110",
      "kubernetes",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 4096
    },
    "names": [
        {
            "C": "CN",
            "ST": "ChengDu",
            "L": "ChengDu",
            "O": "Kubernetes",
            "OU": "System"
        }
    ]
}
EOF

# 生成证书
cd master && cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../config.json -profile=profile master-csr.json | cfssljson -bare master && cd ..

生成 Node 证书

# 创建文件夹
mkdir node
# 写入证书请求文件
cat >node/node-csr.json<<EOF
{
    "CN": "node",
    "hosts": [
      "127.0.0.1",
      "10.1.0.1",
      "10.2.0.1",
      "192.168.56.100",
      "192.168.56.101",
      "192.168.56.102",
      "192.168.56.103",
      "192.168.56.104",
      "192.168.56.105",
      "192.168.56.106",
      "192.168.56.107",
      "192.168.56.108",
      "192.168.56.109",
      "192.168.56.110",
      "kubernetes",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 4096
    },
    "names": [
        {
            "C": "CN",
            "ST": "ChengDu",
            "L": "ChengDu",
            "O": "Kubernetes",
            "OU": "System"
        }
    ]
}
EOF

# 生成证书
cd node && cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../config.json -profile=profile node-csr.json | cfssljson -bare node && cd ..

验证证书

# CA
cfssl-certinfo -cert ca/ca.pem

# Etcd
cfssl-certinfo -cert etcd/etcd.pem

# Master
cfssl-certinfo -cert master/master.pem

# Node
cfssl-certinfo -cert node/node.pem

我这里配置的三个证书授权的 DNS 都是一样的,所以用同一个也可以。但在实际部署生产环境的时候请视情况而定。另外我加了一个 Etcd 是为了适配存在独立的 Etcd 集群的情况。

开始部署

Etcd

Etcdk8s 集群中用来存取数据的很重要的组件,一般部署成集群,这里采用二进制安装。我这里没多苛刻的要求就单节点了,并且和 Master 同一台机器。

官网:https://coreos.com/etcd/

下载地址:https://github.com/coreos/etcd/releases/

为了部署方便我们定义一些变量

# Etcd节点IP,实际替换为部署 IP
export ETCD_IP="192.168.56.100"
# etcd 存储数据前缀
export ETCD_PREFIX="/atomic.io/network"
# etcd 集群服务地址列表
export ETCD_ENDPOINTS="https://192.168.56.100:2379"

# POD 网段 (Cluster CIDR),部署前路由不可达,**部署后**路由可达 (flanneld 保证)
export KUBE_CLUSTER_CIDR="10.2.0.0/16"

准备证书

Etcd 需要用到上面生成的 CA 证书公钥,Etcd 的公私钥(etcd.pemetcd-key.pem

# 创建证书目录
mkdir -p /etc/etcd/ssl

# 拷贝证书
cp -f ~/ca/ca.pem /etc/etcd/ssl
cp -f ~/etcd/{etcd.pem,etcd-key.pem} /etc/etcd/ssl

etcd

# 下载&解压
wget https://github.com/coreos/etcd/releases/download/v3.3.7/etcd-v3.3.7-linux-amd64.tar.gz
tar -zxvf etcd-v3.3.7-linux-amd64.tar.gz

# 拷贝可执行文件到系统环境
cp -r etcd-v3.3.7-linux-amd64/{etcd,etcdctl} /usr/bin/
chmod +x /usr/bin/{etcd,etcdctl}

# 创建工作目录
mkdir -p /var/lib/etcd/data

# 写 Service 文件
cat >/usr/lib/systemd/system/etcd.service<<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
# set GOMAXPROCS to number of processors
ExecStart=/usr/bin/etcd \\
  --name=${ETCD_IP} \\
  --data-dir=/var/lib/etcd/data/ \\
  \\
  --listen-client-urls=https://${ETCD_IP}:2379,http://127.0.0.1:2379 \\
  --listen-peer-urls=https://${ETCD_IP}:2380 \\
  --advertise-client-urls=https://${ETCD_IP}:2379,http://127.0.0.1:2379 \\
  --initial-advertise-peer-urls=https://${ETCD_IP}:2380 \\
  \\
  --cert-file=/etc/etcd/ssl/etcd.pem \\
  --peer-cert-file=/etc/etcd/ssl/etcd.pem \\
  --key-file=/etc/etcd/ssl/etcd-key.pem \\
  --peer-key-file=/etc/etcd/ssl/etcd-key.pem \\
  --trusted-ca-file=/etc/etcd/ssl/ca.pem \\
  --peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \\
  --client-cert-auth=true \\
  --peer-client-cert-auth=true

Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

# 运行&开机启动
systemctl daemon-reload
systemctl start etcd
systemctl enable etcd
systemctl status etcd

添加 flannel 网络数据,注意 ETCD_PREFIX 配置的是前缀,需要跟上一个 config 结尾

# 删除原有配置
etcdctl \
  --endpoints=${ETCD_ENDPOINTS} \
  --cert-file=/etc/etcd/ssl/etcd.pem \
  --key-file=/etc/etcd/ssl/etcd-key.pem \
  --ca-file=/etc/etcd/ssl/ca.pem \
  rm ${ETCD_PREFIX}/config

# 写入新配置
cat <<EOF | etcdctl \
  --endpoints=${ETCD_ENDPOINTS} \
  --cert-file=/etc/etcd/ssl/etcd.pem \
  --key-file=/etc/etcd/ssl/etcd-key.pem \
  --ca-file=/etc/etcd/ssl/ca.pem \
  mk ${ETCD_PREFIX}/config \
'{"Network":"'${KUBE_CLUSTER_CIDR}'","SubnetLen":24,"Backend":{"Type":"vxlan"}}'
EOF

Master

在 Master 节点,需要 kubernetes 系列组件(包括kube-apiserverkube-schedulerkube-controller-managerkubectl,其中 kubectl 非必选)。

这里搭建 Master 只说了纯的 Master 节点,没有包含 dockerflannelkubeletkube-proxy 这些 Node 节点程序,如果需要把 Master 节点当做 Node 节点使用请参照 Node 节点配置安装即可。

为了部署方便我们定义一些变量

# Master 节点IP地址,实际替换为部署 IP
export MASTER_IP="192.168.56.100"

# etcd 存储数据前缀
export ETCD_PREFIX="/atomic.io/network"
# etcd 集群服务地址列表
export ETCD_ENDPOINTS="https://192.168.56.100:2379"

# Master ApiServer 访问地址
export KUBE_APISERVER="https://${MASTER_IP}:6443"
# 服务网段 (Service CIDR),部署前必须路由不可达
export KUBE_SERVICE_CIDR="10.1.0.0/16"
# POD 网段 (Cluster CIDR),部署前路由不可达,**部署后**路由可达 (flanneld 保证)
export KUBE_CLUSTER_CIDR="10.2.0.0/16"
# 节点对外端口范围
export KUBE_PORT_RANGE="10000-60000"

准备证书

Master 需要用到上面生成的 CA 证书公钥,Master 的公私钥(master.pemmaster-key.pem

# 创建证书目录
mkdir -p /etc/kubernetes/ssl

# 拷贝证书
cp -f ~/ca/{ca.pem,ca-key.pem} /etc/kubernetes/ssl
cp -f ~/master/{master.pem,master-key.pem} /etc/kubernetes/ssl

kubernetes

由于这玩意儿在 yum 仓库里的版本十分老旧,就下载二进制文件安装,版本使用最新的 v1.10.4 版本。

官网: https://kubernetes.io/

Kubernetes 其他版本下载地址在 Kubernetes 仓库的变更记录中:CHANGELOG.md

其中 Downloads for vx.x.x 这个是各种脚本,Client Binaries 只包含 kubectlNode Binaries 也只包含 kubectlkubeadmkubeletkube-proxy,而 Server Binaries 才是我们需要的 kube 系列所有应用程序和基础镜像。

准备二进制文件

# 下载&解压
wget https://dl.k8s.io/v1.10.4/kubernetes-server-linux-amd64.tar.gz
tar zxvf kubernetes-server-linux-amd64.tar.gz

# 拷贝可执行文件到系统环境
cp -r kubernetes/server/bin/{kube-apiserver,kube-scheduler,kube-controller-manager,kubectl} /usr/bin/
chmod +x /usr/bin/{kube-apiserver,kube-scheduler,kube-controller-manager,kubectl}

kube-apiserver

创建 kube-apiserverservice 文件(未启用 RBAC 权限控制)

cat >/usr/lib/systemd/system/kube-apiserver.service<<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
ExecStart=/usr/bin/kube-apiserver \\
  --kubelet-https=true \\
  #--authorization-mode=RBAC \\
  --runtime-config=rbac.authorization.k8s.io/v1alpha1 \\
  --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
  \\
  --bind-address=${MASTER_IP} \\
  --advertise-address=${MASTER_IP} \\
  --insecure-bind-address=127.0.0.1 \\
  \\
  --service-node-port-range=${KUBE_PORT_RANGE} \\
  --service-cluster-ip-range=${KUBE_SERVICE_CIDR} \\
  \\
  --client-ca-file=/etc/kubernetes/ssl/ca.pem \\
  --service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \\
  --tls-cert-file=/etc/kubernetes/ssl/master.pem \\
  --tls-private-key-file=/etc/kubernetes/ssl/master-key.pem \\
  --etcd-prefix=${ETCD_PREFIX} \\
  --etcd-servers=${ETCD_ENDPOINTS} \\
  --etcd-cafile=/etc/kubernetes/ssl/ca.pem \\
  --etcd-certfile=/etc/kubernetes/ssl/master.pem \\
  --etcd-keyfile=/etc/kubernetes/ssl/master-key.pem \\
  \\
  --enable-swagger-ui=true \\
  --allow-privileged=true \\
  --apiserver-count=1 \\
  --event-ttl=1h \\
  --v=2

Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF

配置并启动服务

systemctl daemon-reload
systemctl start kube-apiserver
systemctl enable kube-apiserver
systemctl status kube-apiserver

kube-scheduler

创建 kube-schedulerservice 文件

cat >/usr/lib/systemd/system/kube-scheduler.service<<EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart=/usr/bin/kube-scheduler \
  --address=127.0.0.1 \
  --master=http://127.0.0.1:8080 \
  --leader-elect=true \
  --v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF

配置并启动服务

systemctl daemon-reload
systemctl start kube-scheduler
systemctl enable kube-scheduler
systemctl status kube-scheduler

kube-controller-manager

创建 kube-controller-managerservice 文件

cat >/usr/lib/systemd/system/kube-controller-manager.service<<EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart=/usr/bin/kube-controller-manager \\
  --address=127.0.0.1 \\
  --master=http://127.0.0.1:8080 \\
  \\
  --service-cluster-ip-range=${KUBE_SERVICE_CIDR} \\
  --cluster-cidr=${KUBE_CLUSTER_CIDR} \\
  --allocate-node-cidrs=true \\
  --cluster-name=master \\
  \\
  --root-ca-file=/etc/kubernetes/ssl/ca.pem \\
  --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \\
  --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \\
  --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \\
  \\
  --leader-elect=true \\
  --v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF

配置并启动服务

systemctl daemon-reload
systemctl start kube-controller-manager
systemctl enable kube-controller-manager
systemctl status kube-controller-manager

kubectl

kubectl 可以操作集群,上面 kube-apiserver 开启了 127.0.0.1 本地非安全端口,这里 kubectl 不需要配置就可以直接使用。

验证Master状态

kubectl get componentstatuses

NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok                   
controller-manager   Healthy   ok                   
etcd-0               Healthy   {"health": "true"}

创建 Node 的验证配置 node.kubeconfig 文件

# 设置集群参数
kubectl config set-cluster node-cluster \
  --certificate-authority=/root/ca/ca.pem \
  --server=${KUBE_APISERVER} \
  --embed-certs=true \
  --kubeconfig=/root/node/node.kubeconfig

# 设置用户认证参数
kubectl config set-credentials node-credentials \
  --client-certificate=/root/node/node.pem \
  --client-key=/root/node/node-key.pem \
  --embed-certs=true \
  --kubeconfig=/root/node/node.kubeconfig

# 设置上下文参数
kubectl config set-context node-context \
  --cluster=node-cluster \
  --user=node-credentials \
  --kubeconfig=/root/node/node.kubeconfig

# 设置默认上下文
kubectl config use-context node-context \
--kubeconfig=/root/node/node.kubeconfig

Node

在 Node 节点,必须安装 dockerflannelkubernetes 系列组件(包括 kubeletkube-proxy)。

为了部署方便我们定义一些变量

# 当前部署 Node 的 IP
export NODE_IP="192.168.56.102"
# flannel 使用的网卡
export NODE_IFACE="eth1"

# etcd 存储数据前缀
export ETCD_PREFIX="/atomic.io/network"
# etcd 集群服务地址列表
export ETCD_ENDPOINTS="https://192.168.56.100:2379"

# Master 节点IP地址,实际替换为部署 IP
export KUBE_MASTER_IP="192.168.56.100"
# Master ApiServer 访问地址
export KUBE_APISERVER="https://${KUBE_MASTER_IP}:6443"
# 服务网段 (Service CIDR),部署前必须路由不可达
export KUBE_SERVICE_CIDR="10.1.0.0/16"
# kubernetes 服务 IP (预分配,一般是 SERVICE_CIDR 中第一个IP)
export KUBE_SERVICE_SVC_IP="10.1.0.1"
# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)
export KUBE_SERVICE_DNS_IP="10.1.0.2"
# 集群 DNS 域名
export KUBE_SERVICE_DNS_DOMAIN="cluster.local"

准备证书

Node 需要用到上面生成的 CA 证书公钥,Etcd 的公私钥(etcd.pemetcd-key.pem)以及 Node 的验证配置

# 创建证书目录
mkdir -p /etc/kubernetes/ssl

# Master 部署使用
cp -f ~/node/node.kubeconfig /etc/kubernetes
cp -f ~/etcd/{etcd.pem,etcd-key.pem} /etc/kubernetes/ssl

# Node 部署使用
scp root@${KUBE_MASTER_IP}:~/ca/ca.pem /etc/kubernetes/ssl
scp root@${KUBE_MASTER_IP}:~/etcd/{etcd.pem,etcd-key.pem} /etc/kubernetes/ssl
scp root@${KUBE_MASTER_IP}:~/node/node.kubeconfig /etc/kubernetes

docker

Docker 使用目前最新的 Docker-ce-18.03.1

官网:https://www.docker.com/

下载地址:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/

# 下载
wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-18.03.1.ce-1.el7.centos.x86_64.rpm

# 安装 Docker 和依赖包
yum install -y docker*.rpm

# 运行&开机启动
systemctl start docker
systemctl enable docker

flannel

网络插件 Flannel 同样二进制安装,至于其他网络插件大家可以根据需要自行探索。

官网:https://coreos.com/flannel/

下载地址:https://github.com/coreos/flannel/releases

# 下载&解压
wget https://github.com/coreos/flannel/releases/download/v0.10.0/flannel-v0.10.0-linux-amd64.tar.gz
mkdir flannel-v0.10.0-linux-amd64 && tar -zxvf flannel-v0.10.0-linux-amd64.tar.gz -C ./flannel-v0.10.0-linux-amd64

# 拷贝执行文件到系统目录
cp -r flannel-v0.10.0-linux-amd64/{flanneld,mk-docker-opts.sh} /usr/bin/
chmod +x /usr/bin/{flanneld,mk-docker-opts.sh}

# 写入 Service 文件
cat >/usr/lib/systemd/system/flanneld.service<<EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service

[Service]
Type=notify
ExecStart=/usr/bin/flanneld \\
  -iface=${NODE_IFACE} \\
  -etcd-prefix=${ETCD_PREFIX} \\
  -etcd-endpoints=${ETCD_ENDPOINTS} \\
  \\
  -etcd-cafile=/etc/kubernetes/ssl/ca.pem \\
  -etcd-certfile=/etc/kubernetes/ssl/etcd.pem \\
  -etcd-keyfile=/etc/kubernetes/ssl/etcd-key.pem

ExecStartPost=/usr/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure

[Install]
WantedBy=multi-user.target
RequiredBy=docker.service
EOF

# 运行&开机启动
systemctl daemon-reload
systemctl start flanneld
systemctl enable flanneld
systemctl status flanneld

重写 Docker Service 设置 Docker 网络

cat >/usr/lib/systemd/system/docker.service<<'EOF'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target firewalld.service

[Service]
Type=notify
EnvironmentFile=-/run/flannel/docker
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd --log-level=error $DOCKER_NETWORK_OPTIONS
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process

[Install]
WantedBy=multi-user.target
EOF

# 重启 Docker
systemctl daemon-reload
systemctl restart docker

变动如下:

  • 添加配置文件引用 EnvironmentFile=-/run/flannel/docker
  • 添加启动参数 ExecStart=/root/local/bin/dockerd --log-level=error $DOCKER_NETWORK_OPTIONS

kubernetes

由于这玩意儿在 yum 仓库里的版本十分老旧,就下载二进制文件安装,版本使用最新的 v1.10.4 版本。

官网: https://kubernetes.io/

Kubernetes 其他版本下载地址在 Kubernetes 仓库的变更记录中:CHANGELOG.md

其中 Downloads for vx.x.x 这个是各种脚本,Client Binaries 只包含 kubectlNode Binaries 也只包含 kubectlkubeadmkubeletkube-proxy,而 Server Binaries 才是我们需要的 kube 系列所有应用程序和基础镜像。

# 下载&解压
wget https://dl.k8s.io/v1.10.4/kubernetes-server-linux-amd64.tar.gz
tar zxvf kubernetes-server-linux-amd64.tar.gz

# 拷贝可执行文件到系统环境
cp -r kubernetes/server/bin/{kubelet,kube-proxy} /usr/bin/
chmod +x /usr/bin/{kubelet,kube-proxy}

kubelet

创建工作目录

mkdir -p /var/lib/kubelet

创建 kubeletservice 文件

cat >/usr/lib/systemd/system/kubelet.service<<EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/usr/bin/kubelet \\
  --address=${NODE_IP} \\
  --hostname-override=${NODE_IP} \\
  --pod-infra-container-image=registry.cn-shenzhen.aliyuncs.com/lx0758/pause-amd64:3.0 \\
  --kubeconfig=/etc/kubernetes/node.kubeconfig \\
  --cluster_dns=${KUBE_SERVICE_DNS_IP} \\
  --cluster_domain=${KUBE_SERVICE_DNS_DOMAIN}. \\
  --hairpin-mode=promiscuous-bridge \\
  --allow-privileged=true \\
  --serialize-image-pulls=false \\
  --cgroup-driver=cgroupfs \\
  --logtostderr=true \\
  --v=2

Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF

配置并启动服务

systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
systemctl status kubelet

kube-proxy

创建工作目录

mkdir -p /var/lib/kube-proxy

创建 kube-proxyservice 文件

cat >/usr/lib/systemd/system/kube-proxy.service<<EOF
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
WorkingDirectory=/var/lib/kube-proxy
ExecStart=/usr/bin/kube-proxy \\
  --bind-address=${NODE_IP} \\
  --hostname-override=${NODE_IP} \\
  --cluster-cidr=${KUBE_SERVICE_CIDR} \\
  --kubeconfig=/etc/kubernetes/node.kubeconfig \\
  --logtostderr=true \\
  --v=2

Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF

配置并启动服务

systemctl daemon-reload
systemctl start kube-proxy
systemctl enable kube-proxy
systemctl status kube-proxy

安装插件

经过以上步骤,k8s 已经具备了它的核心能力,但要满足日常使用,还需要安装一些必要插件。

CoreDNS

DNS 作为 k8s 的首选插件,这里安装 CoreDNS 插件。

DNS 插件常见的有 kube-dnsCoreDNS,在 kubernetes 仓库中可以找到。
https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/dns
原版 CoreDNS 仓库,包含配置脚本和说明文档。
https://github.com/coredns/deployment/tree/master/kubernetes

首先下载 配置文件yaml 文件

wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/deploy.sh
wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed

准备参数,注意需要和 Node 部署时保持一致

chmod +x deploy.sh
export CLUSTER_DNS_SVC_IP="10.1.0.2"
export CLUSTER_DNS_DOMAIN="cluster.local"

替换镜像

sed -i "s/image:.*/image: registry.cn-shenzhen.aliyuncs.com\/lx0758\/coredns:1.1.3/g" coredns.yaml.sed

安装 DNS 插件

./deploy.sh -i ${CLUSTER_DNS_SVC_IP} -d ${CLUSTER_DNS_DOMAIN} -t coredns.yaml.sed | kubectl apply -f -

Heapster

k8s 的监控组件,自动伸缩与及 Dashboard 都依赖与它。

官方网站:https://github.com/kubernetes/heapster

# 下载 yaml 文件
mkdir -p influxdb && cd influxdb
wget https://github.com/kubernetes/heapster/raw/master/deploy/kube-config/influxdb/heapster.yaml
wget https://github.com/kubernetes/heapster/raw/master/deploy/kube-config/influxdb/influxdb.yaml
wget https://github.com/kubernetes/heapster/raw/master/deploy/kube-config/influxdb/grafana.yaml
cd ..

# 修改镜像
sed -i "s/image:.*/image: registry.cn-shenzhen.aliyuncs.com\/lx0758\/heapster-amd64:v1.5.3/g" ./influxdb/heapster.yaml
sed -i "s/image:.*/image: registry.cn-shenzhen.aliyuncs.com\/lx0758\/heapster-grafana-amd64:v4.4.3/g" ./influxdb/grafana.yaml
sed -i "s/image:.*/image: registry.cn-shenzhen.aliyuncs.com\/lx0758\/heapster-influxdb-amd64:v1.3.3/g" ./influxdb/influxdb.yaml

# 应用插件
kubectl apply -f ./influxdb/

Ingress

集群内自动配置的 nginx 反向代理服务器。

官方网站:NGINX Ingress Controller

# 下载 yaml 文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

# 修改镜像
sed -i "s/image:.*defaultbackend.*/image: registry.cn-shenzhen.aliyuncs.com\/lx0758\/defaultbackend:1.4/g" mandatory.yaml
sed -i "s/image:.*nginx-ingress-controller.*/image: registry.cn-shenzhen.aliyuncs.com\/lx0758\/nginx-ingress-controller:0.15.0/g" mandatory.yaml

# 应用插件
kubectl apply -f mandatory.yaml

注意这个插件还需要用合适的方法暴露给外部使用,否则没有意义。比如在之前使用 kubeadm 部署时是对容器网络映射到物理机的方式进行暴露(hostNetwork: true)。

Node-problem-detector

kubernetes 集群管理对 node 的健康状态是无法感知的,pod 依旧会调度到有问题的 node 上,通过 DaemonSet 部署 node-problem-detector,向 apiserver 上报 node 的状态信息,使 node 的健康状态对上游管理可见,pod 不会再调度到有异常的 node 上。

官方网站:https://github.com/kubernetes/node-problem-detector

# 下载配置文件
wget https://raw.githubusercontent.com/kubernetes/node-problem-detector/master/config/kernel-monitor.json

# 应用配置文件
mkdir /etc/kubernetes/config
mv kernel-monitor.json /etc/kubernetes/config/
kubectl create configmap node-problem-detector-config --from-file=/etc/kubernetes/config/ -n kube-system

# 下载 yaml 文件
wget https://github.com/kubernetes/node-problem-detector/raw/master/deployment/node-problem-detector.yaml

# 修改镜像
sed -i "s/image:.*/image: registry.cn-shenzhen.aliyuncs.com\/lx0758\/node-problem-detector:v0.2/g" node-problem-detector.yaml

# 应用插件
kubectl apply -f node-problem-detector.yaml -n kube-system

引用鸣谢

  1. 和我一步步部署 kubernetes 集群
  2. CentOS上手工部署kubernetes集群