部署node节点

Kubernetes node节点包含如下组件:

  • Flanneld:之前没有配置TLS,现在需要在service配置文件中增加TLS配置。
  • Docker17.12.0-ce:但是需要注意docker的配置。
  • kubelet:直接用二进制文件安装
  • kube-proxy:直接用二进制文件安装 注意:每台 node 上都需要安装 flannel,master 节点上可以不安装。

步骤简介

  1. 安装配置的网络插件flannel已启动且运行正常
  2. 安装配置docker后启动
  3. 安装配置kubelet、kube-proxy后启动
  4. 验证

安装flannel网络插件

所有的node节点都需要安装网络插件才能让所有的Pod加入到同一个局域网中

yum安装flanneld

除非对版本有特殊需求,默认安装的是0.7.1版本的flannel

yum install -y flannel

service配置文件

/usr/lib/systemd/system/flanneld.service 配置文件:

[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
EnvironmentFile=/etc/sysconfig/flanneld
EnvironmentFile=-/etc/sysconfig/docker-network
ExecStart=/usr/bin/flanneld-start \
  -etcd-endpoints=${FLANNEL_ETCD_ENDPOINTS} \
  -etcd-prefix=${FLANNEL_ETCD_PREFIX} \
  $FLANNEL_OPTIONS
ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure
[Install]
WantedBy=multi-user.target
RequiredBy=docker.service

/etc/sysconfig/flanneld 配置文件:

# Flanneld configuration options

# etcd url location. Point this to the server where etcd runs
FLANNEL_ETCD_ENDPOINTS="https://10.80.231.151:2379,https://10.80.230.57:2379,https://10.81.50.223:2379"

# etcd config key. This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/kube-centos/network"

# Any additional options that you want to pass
FLANNEL_OPTIONS="-etcd-cafile=/etc/kubernetes/ssl/ca.pem -etcd-certfile=/etc/etcd/ssl/etcd.pem -etcd-keyfile=/etc/etcd/ssl/etcd-key.pem"

如果是多网卡(例如vagrant环境),则需要在FLANNEL_OPTIONS中增加指定的外网出口的网卡,例如-iface=eth2

在etcd中创建网络配置

执行下面的命令为docker分配IP地址段

$ etcdctl --endpoints=https://10.80.231.151:2379,https://10.80.230.57:2379,https://10.81.50.223:2379 \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/etcd/ssl/etcd.pem \
  --key-file=/etc/etcd/ssl/etcd-key.pem \
  mkdir /kube-centos/network
$ etcdctl --endpoints=https://10.80.231.151:2379,https://10.80.230.57:2379,https://10.81.50.223:2379 \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/etcd/ssl/etcd.pem \
  --key-file=/etc/etcd/ssl/etcd-key.pem \
  mk /kube-centos/network/config '{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}'

启动flannel

mkdir /var/lib/kubelet
systemctl daemon-reload
systemctl enable flanneld
systemctl start flanneld
systemctl status flanneld

验证

[root@hz-k8s-cluster-n02 ~]# etcdctl --endpoints=${ETCD_ENDPOINTS} \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/etcd/ssl/etcd.pem \
  --key-file=/etc/etcd/ssl/etcd-key.pem \
  ls /kube-centos/network/subnets
/kube-centos/network/subnets/172.30.19.0-24
/kube-centos/network/subnets/172.30.71.0-24
[root@hz-k8s-cluster-n02 ~]# etcdctl --endpoints=${ETCD_ENDPOINTS} \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/etcd/ssl/etcd.pem \
  --key-file=/etc/etcd/ssl/etcd-key.pem \
  get /kube-centos/network/config
{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}
[root@hz-k8s-cluster-n02 ~]# etcdctl --endpoints=${ETCD_ENDPOINTS} --ca-file=/etc/kubernetes/ssl/ca.pem --cert-file=/etc/etcd/ssl/etcd.pem --key-file=/etc/etcd/ssl/etcd-key.pem get /kube-centos/network/subnets/172.30.5.0-24
{"PublicIP":"47.96.40.139","BackendType":"vxlan","BackendData":{"VtepMAC":"c2:25:29:32:b6:68"}}
[root@hz-k8s-cluster-n02 ~]# etcdctl --endpoints=${ETCD_ENDPOINTS} --ca-file=/etc/kubernetes/ssl/ca.pem --cert-file=/etc/etcd/ssl/etcd.pem --key-file=/etc/etcd/ssl/etcd-key.pem get /kube-centos/network/subnets/172.30.56.0-24
{"PublicIP":"47.97.26.0","BackendType":"vxlan","BackendData":{"VtepMAC":"2e:fd:42:25:0a:34"}}

查看到以上内容证明flannel已经安装完成

配置docker

yum方式安装的flannel 修改docker的配置文件/usr/lib/systemd/system/docker.service,增加一条环境变量配置:

EnvironmentFile=-/run/flannel/docker

/run/flannel/docker文件是flannel启动后自动生成的,其中包含了docker启动时需要的参数。

安装和配置kubelet

cd /etc/kubernetes
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

安装kubelet

tar -xzvf kubernetes-server-linux-amd64.tar.gz
cd kubernetes
tar -xzvf kubernetes-src.tar.gz
cp -r ./server/bin/{kube-proxy,kubelet} /usr/local/bin/

创建kubelet的service配置文件

文件位置/usr/lib/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
EnvironmentFile=-/etc/kubernetes/config
EnvironmentFile=-/etc/kubernetes/kubelet
ExecStart=/usr/local/bin/kubelet \
            $KUBE_LOGTOSTDERR \
            $KUBE_LOG_LEVEL \
            $KUBELET_API_SERVER \
            $KUBELET_ADDRESS \
            $KUBELET_PORT \
            $KUBELET_HOSTNAME \
            $KUBE_ALLOW_PRIV \
            $KUBELET_POD_INFRA_CONTAINER \
            $KUBELET_ARGS
Restart=on-failure
[Install]
WantedBy=multi-user.target

kubelet的配置文件/etc/kubernetes/kubelet

KUBELET_ADDRESS="--address=10.80.230.57"
KUBELET_HOSTNAME="--hostname-override=10.80.230.57"
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=hub.bbtree.com/kubernetes/pod-infrastructure:latest"
KUBELET_ARGS="--cgroup-driver=cgroupfs --cluster-dns=10.254.0.2 --bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig --kubeconfig=/etc/kubernetes/kubelet.kubeconfig --cert-dir=/etc/kubernetes/ssl --cluster-domain=cluster.local --hairpin-mode promiscuous-bridge --serialize-image-pulls=false"
  • 如果使用systemd方式启动,则需要额外增加两个参数–runtime-cgroups=/systemd/system.slice –kubelet-cgroups=/systemd/system.slice
  • –address 不能设置为 127.0.0.1,否则后续 Pods 访问 kubelet 的 API 接口时会失败,因为 Pods 访问的 127.0.0.1 指向自己而不是 kubelet;
  • 如果设置了 –hostname-override 选项,则 kube-proxy 也需要设置该选项,否则会出现找不到 Node 的情况;
  • ”–cgroup-driver 配置成 systemd,不要使用cgroup,否则在 CentOS 系统中 kubelet 将启动失败(保持docker和kubelet中的cgroup driver配置一致即可,不一定非使用systemd)。
  • –experimental-bootstrap-kubeconfig 指向 bootstrap kubeconfig 文件,kubelet 使用该文件中的用户名和 token 向 kube-apiserver 发送 TLS Bootstrapping 请求;
  • 管理员通过了 CSR 请求后,kubelet 自动在 –cert-dir 目录创建证书和私钥文件(kubelet-client.crt 和 kubelet-client.key),然后写入 –kubeconfig 文件;
  • 建议在 –kubeconfig 配置文件中指定 kube-apiserver 地址,如果未指定 –api-servers 选项,则必须指定 –require-kubeconfig 选项后才从配置文件中读取 kube-apiserver 的地址,否则 kubelet 启动后将找不到 kube-apiserver (日志中提示未找到 API Server),kubectl get nodes 不会返回对应的 Node 信息;
  • –cluster-dns 指定 kubedns 的 Service IP(可以先分配,后续创建 kubedns 服务时指定该 IP),–cluster-domain 指定域名后缀,这两个参数同时指定后才会生效;
  • –cluster-domain 指定 pod 启动时 /etc/resolve.conf 文件中的 search domain ,起初我们将其配置成了 cluster.local.,这样在解析 service 的 DNS 名称时是正常的,可是在解析 headless service 中的 FQDN pod name 的时候却错误,因此我们将其修改为 cluster.local,去掉嘴后面的 ”点号“ 就可以解决该问题,关于 kubernetes 中的域名/服务名称解析请参见我的另一篇文章。
  • –kubeconfig=/etc/kubernetes/kubelet.kubeconfig中指定的kubelet.kubeconfig文件在第一次启动kubelet之前并不存在,请看下文,当通过CSR请求后会自动生成kubelet.kubeconfig文件,如果你的节点上已经生成了~/.kube/config文件,你可以将该文件拷贝到该路径下,并重命名为kubelet.kubeconfig,所有node节点可以共用同一个kubelet.kubeconfig文件,这样新添加的节点就不需要再创建CSR请求就能自动添加到kubernetes集群中。同样,在任意能够访问到kubernetes集群的主机上使用kubectl –kubeconfig命令操作集群时,只要使用~/.kube/config文件就可以通过权限认证,因为这里面已经有认证信息并认为你是admin用户,对集群拥有所有权限。
  • KUBELET_POD_INFRA_CONTAINER 是基础镜像容器,这里我用的是私有镜像仓库地址,大家部署的时候需要修改为自己的镜像。我上传了一个到时速云上,可以直接 docker pull index.tenxcloud.com/jimmy/pod-infrastructure 下载。pod-infrastructure镜像是Redhat制作的,大小接近80M,下载比较耗时,其实该镜像并不运行什么具体进程,可以使用Google的pause镜像gcr.io/google_containers/pause-amd64:3.0,这个镜像只有300多K,或者通过DockerHub下载jimmysong/pause-amd64:3.0。

启动kublet

注意:在启动kubelet之前,需要先手动创建/var/lib/kubelet目录

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

通过 kublet 的 TLS 证书请求

kubelet 首次启动时向 kube-apiserver 发送证书签名请求,必须通过后 kubernetes 系统才会将该 Node 加入到集群。

查看未授权的 CSR 请求

[root@hz-k8s-cluster-n01 kubconfig]# kubectl get csr
NAME AGE REQUESTOR CONDITION
node-csr-KvHYqwpnZkcjK4EcgEjGLmlOE82hvi7ULQVmTHg1VzE 4m kubelet-bootstrap Pending
node-csr-t-s1fFaN7Fo7PXEYvXUZKMUz8d5qqe92bRzZb-4b48M 4m kubelet-bootstrap Pending

通过CSR请求

[root@hz-k8s-cluster-n01 kubconfig]# kubectl certificate approve node-csr-t-s1fFaN7Fo7PXEYvXUZKMUz8d5qqe92bRzZb-4b48M
certificatesigningrequest "node-csr-t-s1fFaN7Fo7PXEYvXUZKMUz8d5qqe92bRzZb-4b48M" approved
[root@hz-k8s-cluster-n01 kubconfig]# kubectl certificate approve node-csr-KvHYqwpnZkcjK4EcgEjGLmlOE82hvi7ULQVmTHg1VzE
certificatesigningrequest "node-csr-KvHYqwpnZkcjK4EcgEjGLmlOE82hvi7ULQVmTHg1VzE" approved
[root@hz-k8s-cluster-n01 kubconfig]# kubectl get csr
NAME AGE REQUESTOR CONDITION
node-csr-KvHYqwpnZkcjK4EcgEjGLmlOE82hvi7ULQVmTHg1VzE 5m kubelet-bootstrap Approved,Issued
node-csr-t-s1fFaN7Fo7PXEYvXUZKMUz8d5qqe92bRzZb-4b48M 5m kubelet-bootstrap Approved,Issued

查看自动生成了 kubelet kubeconfig 文件和公私钥

[root@hz-k8s-cluster-n02 kubernetes]# ll /etc/kubernetes/kubelet.kubeconfig
-rw------- 1 root root 2280 Apr 2 23:13 /etc/kubernetes/kubelet.kubeconfig
[root@hz-k8s-cluster-n02 kubernetes]# ll /etc/kubernetes/ssl/kubelet*
-rw-r--r-- 1 root root 1046 Apr 2 23:13 /etc/kubernetes/ssl/kubelet-client.crt
-rw------- 1 root root 227 Apr 2 23:07 /etc/kubernetes/ssl/kubelet-client.key
-rw-r--r-- 1 root root 1111 Apr 2 22:51 /etc/kubernetes/ssl/kubelet.crt
-rw------- 1 root root 1679 Apr 2 22:51 /etc/kubernetes/ssl/kubelet.key

假如你更新kubernetes的证书,只要没有更新token.csv,当重启kubelet后,该node就会自动加入到kuberentes集群中,而不会重新发送certificaterequest,也不需要在master节点上执行kubectl certificate approve操作。前提是不要删除node节点上的/etc/kubernetes/ssl/kubelet*和/etc/kubernetes/kubelet.kubeconfig文件。否则kubelet启动时会提示找不到证书而失败。

注意:如果启动kubelet的时候见到证书相关的报错,有个trick可以解决这个问题,可以将master节点上的~/.kube/config文件(该文件在安装kubectl命令行工具这一步中将会自动生成)拷贝到node节点的/etc/kubernetes/kubelet.kubeconfig位置,这样就不需要通过CSR,当kubelet启动后就会自动加入的集群中。

配置 kube-proxy

安装conntrack

yum install -y conntrack-toolsconntrack-tools

是一套Linux用户空间连接跟踪工具,用于系统管理员进行交互连接跟踪系统,该模块提供了iptables的状态数据包检查。它包括了用户空间的守护进程conntrackd和命令行界面conntrack。

创建 kube-proxy 的service配置文件

文件路径/usr/lib/systemd/system/kube-proxy.service

[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
EnvironmentFile=-/etc/kubernetes/config
EnvironmentFile=-/etc/kubernetes/proxy
ExecStart=/usr/local/bin/kube-proxy \
        $KUBE_LOGTOSTDERR \
        $KUBE_LOG_LEVEL \
        $KUBE_MASTER \
        $KUBE_PROXY_ARGS
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

kube-proxy配置文件/etc/kubernetes/proxy

###
# kubernetes proxy config

# default config should be adequate

# Add your own!
KUBE_PROXY_ARGS="--bind-address=10.80.230.57 --hostname-override=10.80.230.57 --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig --cluster-cidr=10.254.0.0/16"
  • –hostname-override 参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node,从而不会创建任何 iptables 规则;
  • kube-proxy 根据 –cluster-cidr 判断集群内部和外部流量,指定 –cluster-cidr 或 –masquerade-all 选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT;
  • –kubeconfig 指定的配置文件嵌入了 kube-apiserver 的地址、用户名、证书、秘钥等请求和认证信息;
  • 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;

启动 kube-proxy

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

验证测试

我们创建一个nginx的service试一下集群是否可用。

[root@hz-k8s-cluster-n01 example]# kubectl run nginx --replicas=2 --labels="run=load-balancer-example" --image=hub.bbtree.com/library/nginx:v1.9.9 --port=80
deployment "nginx" created
[root@hz-k8s-cluster-n01 example]# kubectl expose deployment nginx --type=NodePort --name=example-service
service "example-service" exposed
[root@hz-k8s-cluster-n01 example]# kubectl describe svc example-service
Name: example-service
Namespace: default
Labels: run=load-balancer-example
Annotations: <none>
Selector: run=load-balancer-example
Type: NodePort
IP: 10.254.49.120
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 31684/TCP
Endpoints: 192.168.0.3:80,192.168.0.3:80
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
[root@hz-k8s-cluster-n02 ~]# curl "10.254.49.120:80"
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

FAQ

1

kubelet[23848]: -v,--v Level
log level for V logs
kubelet[23848]: --ersion version[=true]

配置选项有问题/etc/kubernetes/kubelet

2

error: failed to run Kubelet: unable to load bootstrap kubeconfig: invalid configuration: no configuration has been provided

重新生成:bootstrap.kubeconfig拷贝到node

3

kubelet: error: failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgroupfs"

增加或者修改成配置/etc/kubernetes/kubelet选项 –cgroup-driver=cgroupfs

4

kubelet[22825]: E0403 16:09:53.073634 22825 fs.go:418] Stat fs failed. Error: no such file or directory

重启机器,删除已经创建的pod和service

Search

    Table of Contents